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> verifyRoundtrip(
163  "verify-roundtrip",
164  cl::desc("Round-trip the IR after parsing and ensure it succeeds"),
165  cl::location(verifyRoundtripFlag), cl::init(false));
166 
167  static cl::list<std::string> passPlugins(
168  "load-pass-plugin", cl::desc("Load passes from plugin library"));
169 
170  static cl::opt<std::string, /*ExternalStorage=*/true>
171  generateReproducerFile(
172  "mlir-generate-reproducer",
173  llvm::cl::desc(
174  "Generate an mlir reproducer at the provided filename"
175  " (no crash required)"),
176  cl::location(generateReproducerFileFlag), cl::init(""),
177  cl::value_desc("filename"));
178 
179  /// Set the callback to load a pass plugin.
180  passPlugins.setCallback([&](const std::string &pluginPath) {
181  auto plugin = PassPlugin::load(pluginPath);
182  if (!plugin) {
183  errs() << "Failed to load passes from '" << pluginPath
184  << "'. Request ignored.\n";
185  return;
186  }
187  plugin.get().registerPassRegistryCallbacks();
188  });
189 
190  static cl::list<std::string> dialectPlugins(
191  "load-dialect-plugin", cl::desc("Load dialects from plugin library"));
192  this->dialectPlugins = std::addressof(dialectPlugins);
193 
194  static PassPipelineCLParser passPipeline("", "Compiler passes to run", "p");
195  setPassPipelineParser(passPipeline);
196  }
197 
198  /// Set the callback to load a dialect plugin.
199  void setDialectPluginsCallback(DialectRegistry &registry);
200 
201  /// Pointer to static dialectPlugins variable in constructor, needed by
202  /// setDialectPluginsCallback(DialectRegistry&).
203  cl::list<std::string> *dialectPlugins = nullptr;
204 };
205 } // namespace
206 
207 ManagedStatic<MlirOptMainConfigCLOptions> clOptionsConfig;
208 
210  clOptionsConfig->setDialectPluginsCallback(registry);
212 }
213 
216  return *clOptionsConfig;
217 }
218 
220  const PassPipelineCLParser &passPipeline) {
221  passPipelineCallback = [&](PassManager &pm) {
222  auto errorHandler = [&](const Twine &msg) {
223  emitError(UnknownLoc::get(pm.getContext())) << msg;
224  return failure();
225  };
226  if (failed(passPipeline.addToPipeline(pm, errorHandler)))
227  return failure();
228  if (this->shouldDumpPassPipeline()) {
229 
230  pm.dump();
231  llvm::errs() << "\n";
232  }
233  return success();
234  };
235  return *this;
236 }
237 
238 void MlirOptMainConfigCLOptions::setDialectPluginsCallback(
239  DialectRegistry &registry) {
240  dialectPlugins->setCallback([&](const std::string &pluginPath) {
241  auto plugin = DialectPlugin::load(pluginPath);
242  if (!plugin) {
243  errs() << "Failed to load dialect plugin from '" << pluginPath
244  << "'. Request ignored.\n";
245  return;
246  };
247  plugin.get().registerDialectRegistryCallbacks(registry);
248  });
249 }
250 
251 LogicalResult loadIRDLDialects(StringRef irdlFile, MLIRContext &ctx) {
252  DialectRegistry registry;
253  registry.insert<irdl::IRDLDialect>();
254  ctx.appendDialectRegistry(registry);
255 
256  // Set up the input file.
257  std::string errorMessage;
258  std::unique_ptr<MemoryBuffer> file = openInputFile(irdlFile, &errorMessage);
259  if (!file) {
260  emitError(UnknownLoc::get(&ctx)) << errorMessage;
261  return failure();
262  }
263 
264  // Give the buffer to the source manager.
265  // This will be picked up by the parser.
266  SourceMgr sourceMgr;
267  sourceMgr.AddNewSourceBuffer(std::move(file), SMLoc());
268 
269  SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, &ctx);
270 
271  // Parse the input file.
272  OwningOpRef<ModuleOp> module(parseSourceFile<ModuleOp>(sourceMgr, &ctx));
273  if (!module)
274  return failure();
275 
276  // Load IRDL dialects.
277  return irdl::loadDialects(module.get());
278 }
279 
280 // Return success if the module can correctly round-trip. This intended to test
281 // that the custom printers/parsers are complete.
282 static LogicalResult doVerifyRoundTrip(Operation *op,
283  const MlirOptMainConfig &config,
284  bool useBytecode) {
285  // We use a new context to avoid resource handle renaming issue in the diff.
286  MLIRContext roundtripContext;
287  OwningOpRef<Operation *> roundtripModule;
288  roundtripContext.appendDialectRegistry(
289  op->getContext()->getDialectRegistry());
291  roundtripContext.allowUnregisteredDialects();
292  StringRef irdlFile = config.getIrdlFile();
293  if (!irdlFile.empty() && failed(loadIRDLDialects(irdlFile, roundtripContext)))
294  return failure();
295 
296  std::string testType = (useBytecode) ? "bytecode" : "textual";
297  // Print a first time with custom format (or bytecode) and parse it back to
298  // the roundtripModule.
299  {
300  std::string buffer;
301  llvm::raw_string_ostream ostream(buffer);
302  if (useBytecode) {
303  if (failed(writeBytecodeToFile(op, ostream))) {
304  op->emitOpError()
305  << "failed to write bytecode, cannot verify round-trip.\n";
306  return failure();
307  }
308  } else {
309  op->print(ostream,
310  OpPrintingFlags().printGenericOpForm().enableDebugInfo());
311  }
312  FallbackAsmResourceMap fallbackResourceMap;
313  ParserConfig parseConfig(&roundtripContext, /*verifyAfterParse=*/true,
314  &fallbackResourceMap);
315  roundtripModule =
316  parseSourceString<Operation *>(ostream.str(), parseConfig);
317  if (!roundtripModule) {
318  op->emitOpError() << "failed to parse " << testType
319  << " content back, cannot verify round-trip.\n";
320  return failure();
321  }
322  }
323 
324  // Print in the generic form for the reference module and the round-tripped
325  // one and compare the outputs.
326  std::string reference, roundtrip;
327  {
328  llvm::raw_string_ostream ostreamref(reference);
329  op->print(ostreamref,
330  OpPrintingFlags().printGenericOpForm().enableDebugInfo());
331  llvm::raw_string_ostream ostreamrndtrip(roundtrip);
332  roundtripModule.get()->print(
333  ostreamrndtrip,
334  OpPrintingFlags().printGenericOpForm().enableDebugInfo());
335  }
336  if (reference != roundtrip) {
337  // TODO implement a diff.
338  return op->emitOpError()
339  << testType
340  << " roundTrip testing roundtripped module differs "
341  "from reference:\n<<<<<<Reference\n"
342  << reference << "\n=====\n"
343  << roundtrip << "\n>>>>>roundtripped\n";
344  }
345 
346  return success();
347 }
348 
349 static LogicalResult doVerifyRoundTrip(Operation *op,
350  const MlirOptMainConfig &config) {
351  auto txtStatus = doVerifyRoundTrip(op, config, /*useBytecode=*/false);
352  auto bcStatus = doVerifyRoundTrip(op, config, /*useBytecode=*/true);
353  return success(succeeded(txtStatus) && succeeded(bcStatus));
354 }
355 
356 /// Perform the actions on the input file indicated by the command line flags
357 /// within the specified context.
358 ///
359 /// This typically parses the main source file, runs zero or more optimization
360 /// passes, then prints the output.
361 ///
362 static LogicalResult
363 performActions(raw_ostream &os,
364  const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
365  MLIRContext *context, const MlirOptMainConfig &config) {
368  TimingScope timing = tm.getRootScope();
369 
370  // Disable multi-threading when parsing the input file. This removes the
371  // unnecessary/costly context synchronization when parsing.
372  bool wasThreadingEnabled = context->isMultithreadingEnabled();
373  context->disableMultithreading();
374 
375  // Prepare the parser config, and attach any useful/necessary resource
376  // handlers. Unhandled external resources are treated as passthrough, i.e.
377  // they are not processed and will be emitted directly to the output
378  // untouched.
379  PassReproducerOptions reproOptions;
380  FallbackAsmResourceMap fallbackResourceMap;
381  ParserConfig parseConfig(context, /*verifyAfterParse=*/true,
382  &fallbackResourceMap);
383  if (config.shouldRunReproducer())
384  reproOptions.attachResourceParser(parseConfig);
385 
386  // Parse the input file and reset the context threading state.
387  TimingScope parserTiming = timing.nest("Parser");
389  sourceMgr, parseConfig, !config.shouldUseExplicitModule());
390  parserTiming.stop();
391  if (!op)
392  return failure();
393 
394  // Perform round-trip verification if requested
395  if (config.shouldVerifyRoundtrip() &&
396  failed(doVerifyRoundTrip(op.get(), config)))
397  return failure();
398 
399  context->enableMultithreading(wasThreadingEnabled);
400 
401  // Prepare the pass manager, applying command-line and reproducer options.
403  pm.enableVerifier(config.shouldVerifyPasses());
404  if (failed(applyPassManagerCLOptions(pm)))
405  return failure();
406  pm.enableTiming(timing);
407  if (config.shouldRunReproducer() && failed(reproOptions.apply(pm)))
408  return failure();
409  if (failed(config.setupPassPipeline(pm)))
410  return failure();
411 
412  // Run the pipeline.
413  if (failed(pm.run(*op)))
414  return failure();
415 
416  // Generate reproducers if requested
417  if (!config.getReproducerFilename().empty()) {
418  StringRef anchorName = pm.getAnyOpAnchorName();
419  const auto &passes = pm.getPasses();
420  makeReproducer(anchorName, passes, op.get(),
421  config.getReproducerFilename());
422  }
423 
424  // Print the output.
425  TimingScope outputTiming = timing.nest("Output");
426  if (config.shouldEmitBytecode()) {
427  BytecodeWriterConfig writerConfig(fallbackResourceMap);
428  if (auto v = config.bytecodeVersionToEmit())
429  writerConfig.setDesiredBytecodeVersion(*v);
431  writerConfig.setElideResourceDataFlag();
432  return writeBytecodeToFile(op.get(), os, writerConfig);
433  }
434 
435  if (config.bytecodeVersionToEmit().has_value())
436  return emitError(UnknownLoc::get(pm.getContext()))
437  << "bytecode version while not emitting bytecode";
438  AsmState asmState(op.get(), OpPrintingFlags(), /*locationMap=*/nullptr,
439  &fallbackResourceMap);
440  op.get()->print(os, asmState);
441  os << '\n';
442  return success();
443 }
444 
445 /// Parses the memory buffer. If successfully, run a series of passes against
446 /// it and print the result.
447 static LogicalResult processBuffer(raw_ostream &os,
448  std::unique_ptr<MemoryBuffer> ownedBuffer,
449  const MlirOptMainConfig &config,
450  DialectRegistry &registry,
451  llvm::ThreadPoolInterface *threadPool) {
452  // Tell sourceMgr about this buffer, which is what the parser will pick up.
453  auto sourceMgr = std::make_shared<SourceMgr>();
454  sourceMgr->AddNewSourceBuffer(std::move(ownedBuffer), SMLoc());
455 
456  // Create a context just for the current buffer. Disable threading on creation
457  // since we'll inject the thread-pool separately.
459  if (threadPool)
460  context.setThreadPool(*threadPool);
461 
462  StringRef irdlFile = config.getIrdlFile();
463  if (!irdlFile.empty() && failed(loadIRDLDialects(irdlFile, context)))
464  return failure();
465 
466  // Parse the input file.
468  if (config.shouldVerifyDiagnostics())
469  context.printOpOnDiagnostic(false);
470 
471  tracing::InstallDebugHandler installDebugHandler(context,
472  config.getDebugConfig());
473 
474  // If we are in verify diagnostics mode then we have a lot of work to do,
475  // otherwise just perform the actions without worrying about it.
476  if (!config.shouldVerifyDiagnostics()) {
477  SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context);
478  return performActions(os, sourceMgr, &context, config);
479  }
480 
481  SourceMgrDiagnosticVerifierHandler sourceMgrHandler(*sourceMgr, &context);
482 
483  // Do any processing requested by command line flags. We don't care whether
484  // these actions succeed or fail, we only care what diagnostics they produce
485  // and whether they match our expectations.
486  (void)performActions(os, sourceMgr, &context, config);
487 
488  // Verify the diagnostic handler to make sure that each of the diagnostics
489  // matched.
490  return sourceMgrHandler.verify();
491 }
492 
493 std::pair<std::string, std::string>
494 mlir::registerAndParseCLIOptions(int argc, char **argv,
495  llvm::StringRef toolName,
496  DialectRegistry &registry) {
497  static cl::opt<std::string> inputFilename(
498  cl::Positional, cl::desc("<input file>"), cl::init("-"));
499 
500  static cl::opt<std::string> outputFilename("o", cl::desc("Output filename"),
501  cl::value_desc("filename"),
502  cl::init("-"));
503  // Register any command line options.
510 
511  // Build the list of dialects as a header for the --help message.
512  std::string helpHeader = (toolName + "\nAvailable Dialects: ").str();
513  {
514  llvm::raw_string_ostream os(helpHeader);
515  interleaveComma(registry.getDialectNames(), os,
516  [&](auto name) { os << name; });
517  }
518  // Parse pass names in main to ensure static initialization completed.
519  cl::ParseCommandLineOptions(argc, argv, helpHeader);
520  return std::make_pair(inputFilename.getValue(), outputFilename.getValue());
521 }
522 
523 static LogicalResult printRegisteredDialects(DialectRegistry &registry) {
524  llvm::outs() << "Available Dialects: ";
525  interleave(registry.getDialectNames(), llvm::outs(), ",");
526  llvm::outs() << "\n";
527  return success();
528 }
529 
530 static LogicalResult printRegisteredPassesAndReturn() {
532  return success();
533 }
534 
535 LogicalResult mlir::MlirOptMain(llvm::raw_ostream &outputStream,
536  std::unique_ptr<llvm::MemoryBuffer> buffer,
537  DialectRegistry &registry,
538  const MlirOptMainConfig &config) {
539  if (config.shouldShowDialects())
540  return printRegisteredDialects(registry);
541 
542  if (config.shouldListPasses())
544 
545  // The split-input-file mode is a very specific mode that slices the file
546  // up into small pieces and checks each independently.
547  // We use an explicit threadpool to avoid creating and joining/destroying
548  // threads for each of the split.
549  ThreadPoolInterface *threadPool = nullptr;
550 
551  // Create a temporary context for the sake of checking if
552  // --mlir-disable-threading was passed on the command line.
553  // We use the thread-pool this context is creating, and avoid
554  // creating any thread when disabled.
555  MLIRContext threadPoolCtx;
556  if (threadPoolCtx.isMultithreadingEnabled())
557  threadPool = &threadPoolCtx.getThreadPool();
558 
559  auto chunkFn = [&](std::unique_ptr<MemoryBuffer> chunkBuffer,
560  raw_ostream &os) {
561  return processBuffer(os, std::move(chunkBuffer), config, registry,
562  threadPool);
563  };
564  return splitAndProcessBuffer(std::move(buffer), chunkFn, outputStream,
565  config.inputSplitMarker(),
566  config.outputSplitMarker());
567 }
568 
569 LogicalResult mlir::MlirOptMain(int argc, char **argv,
570  llvm::StringRef inputFilename,
571  llvm::StringRef outputFilename,
572  DialectRegistry &registry) {
573 
574  InitLLVM y(argc, argv);
575 
577 
578  if (config.shouldShowDialects())
579  return printRegisteredDialects(registry);
580 
581  if (config.shouldListPasses())
583 
584  // When reading from stdin and the input is a tty, it is often a user mistake
585  // and the process "appears to be stuck". Print a message to let the user know
586  // about it!
587  if (inputFilename == "-" &&
588  sys::Process::FileDescriptorIsDisplayed(fileno(stdin)))
589  llvm::errs() << "(processing input from stdin now, hit ctrl-c/ctrl-d to "
590  "interrupt)\n";
591 
592  // Set up the input file.
593  std::string errorMessage;
594  auto file = openInputFile(inputFilename, &errorMessage);
595  if (!file) {
596  llvm::errs() << errorMessage << "\n";
597  return failure();
598  }
599 
600  auto output = openOutputFile(outputFilename, &errorMessage);
601  if (!output) {
602  llvm::errs() << errorMessage << "\n";
603  return failure();
604  }
605  if (failed(MlirOptMain(output->os(), std::move(file), registry, config)))
606  return failure();
607 
608  // Keep the output file if the invocation of MlirOptMain was successful.
609  output->keep();
610  return success();
611 }
612 
613 LogicalResult mlir::MlirOptMain(int argc, char **argv, llvm::StringRef toolName,
614  DialectRegistry &registry) {
615 
616  // Register and parse command line options.
617  std::string inputFilename, outputFilename;
618  std::tie(inputFilename, outputFilename) =
619  registerAndParseCLIOptions(argc, argv, toolName, registry);
620 
621  return MlirOptMain(argc, argv, inputFilename, outputFilename, registry);
622 }
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:533
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:412
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:191
std::optional< int64_t > bytecodeVersionToEmit() const
Definition: MlirOptMain.h:101
StringRef getReproducerFilename() const
Reproducer file generation (no crash required).
Definition: MlirOptMain.h:194
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 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
OperationName getName()
The name of an operation is the key identifier for it.
Definition: Operation.h:119
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:460
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:846
void enableVerifier(bool enabled=true)
Runs the verifier after each individual pass.
Definition: Pass.cpp:843
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:558
This class is a utility diagnostic handler for use with llvm::SourceMgr that verifies that emitted di...
Definition: Diagnostics.h:624
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.