MLIR  16.0.0git
MLIRContext.cpp
Go to the documentation of this file.
1 //===- MLIRContext.cpp - MLIR Type Classes --------------------------------===//
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 #include "mlir/IR/MLIRContext.h"
10 #include "AffineExprDetail.h"
11 #include "AffineMapDetail.h"
12 #include "AttributeDetail.h"
13 #include "IntegerSetDetail.h"
14 #include "TypeDetail.h"
15 #include "mlir/IR/AffineExpr.h"
16 #include "mlir/IR/AffineMap.h"
17 #include "mlir/IR/Attributes.h"
18 #include "mlir/IR/BuiltinDialect.h"
19 #include "mlir/IR/Diagnostics.h"
20 #include "mlir/IR/Dialect.h"
22 #include "mlir/IR/IntegerSet.h"
23 #include "mlir/IR/Location.h"
25 #include "mlir/IR/Types.h"
27 #include "llvm/ADT/DenseMap.h"
28 #include "llvm/ADT/DenseSet.h"
29 #include "llvm/ADT/SmallString.h"
30 #include "llvm/ADT/StringSet.h"
31 #include "llvm/ADT/Twine.h"
32 #include "llvm/Support/Allocator.h"
33 #include "llvm/Support/CommandLine.h"
34 #include "llvm/Support/Debug.h"
35 #include "llvm/Support/Mutex.h"
36 #include "llvm/Support/RWMutex.h"
37 #include "llvm/Support/ThreadPool.h"
38 #include "llvm/Support/raw_ostream.h"
39 #include <memory>
40 
41 #define DEBUG_TYPE "mlircontext"
42 
43 using namespace mlir;
44 using namespace mlir::detail;
45 
46 //===----------------------------------------------------------------------===//
47 // MLIRContext CommandLine Options
48 //===----------------------------------------------------------------------===//
49 
50 namespace {
51 /// This struct contains command line options that can be used to initialize
52 /// various bits of an MLIRContext. This uses a struct wrapper to avoid the need
53 /// for global command line options.
54 struct MLIRContextOptions {
55  llvm::cl::opt<bool> disableThreading{
56  "mlir-disable-threading",
57  llvm::cl::desc("Disable multi-threading within MLIR, overrides any "
58  "further call to MLIRContext::enableMultiThreading()")};
59 
60  llvm::cl::opt<bool> printOpOnDiagnostic{
61  "mlir-print-op-on-diagnostic",
62  llvm::cl::desc("When a diagnostic is emitted on an operation, also print "
63  "the operation as an attached note"),
64  llvm::cl::init(true)};
65 
66  llvm::cl::opt<bool> printStackTraceOnDiagnostic{
67  "mlir-print-stacktrace-on-diagnostic",
68  llvm::cl::desc("When a diagnostic is emitted, also print the stack trace "
69  "as an attached note")};
70 };
71 } // namespace
72 
73 static llvm::ManagedStatic<MLIRContextOptions> clOptions;
74 
76 #if LLVM_ENABLE_THREADS != 0
77  return clOptions.isConstructed() && clOptions->disableThreading;
78 #else
79  return true;
80 #endif
81 }
82 
83 /// Register a set of useful command-line options that can be used to configure
84 /// various flags within the MLIRContext. These flags are used when constructing
85 /// an MLIR context for initialization.
87  // Make sure that the options struct has been initialized.
88  *clOptions;
89 }
90 
91 //===----------------------------------------------------------------------===//
92 // Locking Utilities
93 //===----------------------------------------------------------------------===//
94 
95 namespace {
96 /// Utility writer lock that takes a runtime flag that specifies if we really
97 /// need to lock.
98 struct ScopedWriterLock {
99  ScopedWriterLock(llvm::sys::SmartRWMutex<true> &mutexParam, bool shouldLock)
100  : mutex(shouldLock ? &mutexParam : nullptr) {
101  if (mutex)
102  mutex->lock();
103  }
104  ~ScopedWriterLock() {
105  if (mutex)
106  mutex->unlock();
107  }
108  llvm::sys::SmartRWMutex<true> *mutex;
109 };
110 } // namespace
111 
112 //===----------------------------------------------------------------------===//
113 // MLIRContextImpl
114 //===----------------------------------------------------------------------===//
115 
116 namespace mlir {
117 /// This is the implementation of the MLIRContext class, using the pImpl idiom.
118 /// This class is completely private to this file, so everything is public.
120 public:
121  //===--------------------------------------------------------------------===//
122  // Debugging
123  //===--------------------------------------------------------------------===//
124 
125  /// An action manager for use within the context.
127 
128  //===--------------------------------------------------------------------===//
129  // Diagnostics
130  //===--------------------------------------------------------------------===//
132 
133  //===--------------------------------------------------------------------===//
134  // Options
135  //===--------------------------------------------------------------------===//
136 
137  /// In most cases, creating operation in unregistered dialect is not desired
138  /// and indicate a misconfiguration of the compiler. This option enables to
139  /// detect such use cases
140  bool allowUnregisteredDialects = false;
141 
142  /// Enable support for multi-threading within MLIR.
143  bool threadingIsEnabled = true;
144 
145  /// Track if we are currently executing in a threaded execution environment
146  /// (like the pass-manager): this is only a debugging feature to help reducing
147  /// the chances of data races one some context APIs.
148 #ifndef NDEBUG
149  std::atomic<int> multiThreadedExecutionContext{0};
150 #endif
151 
152  /// If the operation should be attached to diagnostics printed via the
153  /// Operation::emit methods.
154  bool printOpOnDiagnostic = true;
155 
156  /// If the current stack trace should be attached when emitting diagnostics.
157  bool printStackTraceOnDiagnostic = false;
158 
159  //===--------------------------------------------------------------------===//
160  // Other
161  //===--------------------------------------------------------------------===//
162 
163  /// This points to the ThreadPool used when processing MLIR tasks in parallel.
164  /// It can't be nullptr when multi-threading is enabled. Otherwise if
165  /// multi-threading is disabled, and the threadpool wasn't externally provided
166  /// using `setThreadPool`, this will be nullptr.
167  llvm::ThreadPool *threadPool = nullptr;
168 
169  /// In case where the thread pool is owned by the context, this ensures
170  /// destruction with the context.
171  std::unique_ptr<llvm::ThreadPool> ownedThreadPool;
172 
173  /// This is a list of dialects that are created referring to this context.
174  /// The MLIRContext owns the objects.
177 
178  /// An allocator used for AbstractAttribute and AbstractType objects.
179  llvm::BumpPtrAllocator abstractDialectSymbolAllocator;
180 
181  /// This is a mapping from operation name to the operation info describing it.
182  llvm::StringMap<OperationName::Impl> operations;
183 
184  /// A vector of operation info specifically for registered operations.
185  llvm::StringMap<RegisteredOperationName> registeredOperations;
186 
187  /// This is a sorted container of registered operations for a deterministic
188  /// and efficient `getRegisteredOperations` implementation.
190 
191  /// A mutex used when accessing operation information.
192  llvm::sys::SmartRWMutex<true> operationInfoMutex;
193 
194  //===--------------------------------------------------------------------===//
195  // Affine uniquing
196  //===--------------------------------------------------------------------===//
197 
198  // Affine expression, map and integer set uniquing.
200 
201  //===--------------------------------------------------------------------===//
202  // Type uniquing
203  //===--------------------------------------------------------------------===//
204 
207 
208  /// Cached Type Instances.
209  Float8E5M2Type f8E5M2Ty;
210  Float8E4M3FNType f8E4M3FNTy;
211  BFloat16Type bf16Ty;
212  Float16Type f16Ty;
213  Float32Type f32Ty;
214  Float64Type f64Ty;
215  Float80Type f80Ty;
216  Float128Type f128Ty;
217  IndexType indexTy;
218  IntegerType int1Ty, int8Ty, int16Ty, int32Ty, int64Ty, int128Ty;
219  NoneType noneType;
220 
221  //===--------------------------------------------------------------------===//
222  // Attribute uniquing
223  //===--------------------------------------------------------------------===//
224 
227 
228  /// Cached Attribute Instances.
229  BoolAttr falseAttr, trueAttr;
230  UnitAttr unitAttr;
231  UnknownLoc unknownLocAttr;
232  DictionaryAttr emptyDictionaryAttr;
233  StringAttr emptyStringAttr;
234 
235  /// Map of string attributes that may reference a dialect, that are awaiting
236  /// that dialect to be loaded.
240 
241 public:
242  MLIRContextImpl(bool threadingIsEnabled)
243  : threadingIsEnabled(threadingIsEnabled) {
244  if (threadingIsEnabled) {
245  ownedThreadPool = std::make_unique<llvm::ThreadPool>();
246  threadPool = ownedThreadPool.get();
247  }
248  }
250  for (auto typeMapping : registeredTypes)
251  typeMapping.second->~AbstractType();
252  for (auto attrMapping : registeredAttributes)
253  attrMapping.second->~AbstractAttribute();
254  }
255 };
256 } // namespace mlir
257 
259  : MLIRContext(DialectRegistry(), setting) {}
260 
262  : impl(new MLIRContextImpl(setting == Threading::ENABLED &&
264  // Initialize values based on the command line flags if they were provided.
265  if (clOptions.isConstructed()) {
266  printOpOnDiagnostic(clOptions->printOpOnDiagnostic);
267  printStackTraceOnDiagnostic(clOptions->printStackTraceOnDiagnostic);
268  }
269 
270  // Pre-populate the registry.
271  registry.appendTo(impl->dialectsRegistry);
272 
273  // Ensure the builtin dialect is always pre-loaded.
274  getOrLoadDialect<BuiltinDialect>();
275 
276  // Initialize several common attributes and types to avoid the need to lock
277  // the context when accessing them.
278 
279  //// Types.
280  /// Floating-point Types.
281  impl->f8E5M2Ty = TypeUniquer::get<Float8E5M2Type>(this);
282  impl->f8E4M3FNTy = TypeUniquer::get<Float8E4M3FNType>(this);
283  impl->bf16Ty = TypeUniquer::get<BFloat16Type>(this);
284  impl->f16Ty = TypeUniquer::get<Float16Type>(this);
285  impl->f32Ty = TypeUniquer::get<Float32Type>(this);
286  impl->f64Ty = TypeUniquer::get<Float64Type>(this);
287  impl->f80Ty = TypeUniquer::get<Float80Type>(this);
288  impl->f128Ty = TypeUniquer::get<Float128Type>(this);
289  /// Index Type.
290  impl->indexTy = TypeUniquer::get<IndexType>(this);
291  /// Integer Types.
292  impl->int1Ty = TypeUniquer::get<IntegerType>(this, 1, IntegerType::Signless);
293  impl->int8Ty = TypeUniquer::get<IntegerType>(this, 8, IntegerType::Signless);
294  impl->int16Ty =
295  TypeUniquer::get<IntegerType>(this, 16, IntegerType::Signless);
296  impl->int32Ty =
297  TypeUniquer::get<IntegerType>(this, 32, IntegerType::Signless);
298  impl->int64Ty =
299  TypeUniquer::get<IntegerType>(this, 64, IntegerType::Signless);
300  impl->int128Ty =
301  TypeUniquer::get<IntegerType>(this, 128, IntegerType::Signless);
302  /// None Type.
303  impl->noneType = TypeUniquer::get<NoneType>(this);
304 
305  //// Attributes.
306  //// Note: These must be registered after the types as they may generate one
307  //// of the above types internally.
308  /// Unknown Location Attribute.
309  impl->unknownLocAttr = AttributeUniquer::get<UnknownLoc>(this);
310  /// Bool Attributes.
311  impl->falseAttr = IntegerAttr::getBoolAttrUnchecked(impl->int1Ty, false);
312  impl->trueAttr = IntegerAttr::getBoolAttrUnchecked(impl->int1Ty, true);
313  /// Unit Attribute.
314  impl->unitAttr = AttributeUniquer::get<UnitAttr>(this);
315  /// The empty dictionary attribute.
316  impl->emptyDictionaryAttr = DictionaryAttr::getEmptyUnchecked(this);
317  /// The empty string attribute.
318  impl->emptyStringAttr = StringAttr::getEmptyStringAttrUnchecked(this);
319 
320  // Register the affine storage objects with the uniquer.
321  impl->affineUniquer
322  .registerParametricStorageType<AffineBinaryOpExprStorage>();
323  impl->affineUniquer
324  .registerParametricStorageType<AffineConstantExprStorage>();
325  impl->affineUniquer.registerParametricStorageType<AffineDimExprStorage>();
326  impl->affineUniquer.registerParametricStorageType<AffineMapStorage>();
327  impl->affineUniquer.registerParametricStorageType<IntegerSetStorage>();
328 }
329 
330 MLIRContext::~MLIRContext() = default;
331 
332 /// Copy the specified array of elements into memory managed by the provided
333 /// bump pointer allocator. This assumes the elements are all PODs.
334 template <typename T>
335 static ArrayRef<T> copyArrayRefInto(llvm::BumpPtrAllocator &allocator,
336  ArrayRef<T> elements) {
337  auto result = allocator.Allocate<T>(elements.size());
338  std::uninitialized_copy(elements.begin(), elements.end(), result);
339  return ArrayRef<T>(result, elements.size());
340 }
341 
342 //===----------------------------------------------------------------------===//
343 // Debugging
344 //===----------------------------------------------------------------------===//
345 
347  return getImpl().debugActionManager;
348 }
349 
350 //===----------------------------------------------------------------------===//
351 // Diagnostic Handlers
352 //===----------------------------------------------------------------------===//
353 
354 /// Returns the diagnostic engine for this context.
356 
357 //===----------------------------------------------------------------------===//
358 // Dialect and Operation Registration
359 //===----------------------------------------------------------------------===//
360 
362  if (registry.isSubsetOf(impl->dialectsRegistry))
363  return;
364 
365  assert(impl->multiThreadedExecutionContext == 0 &&
366  "appending to the MLIRContext dialect registry while in a "
367  "multi-threaded execution context");
368  registry.appendTo(impl->dialectsRegistry);
369 
370  // For the already loaded dialects, apply any possible extensions immediately.
371  registry.applyExtensions(this);
372 }
373 
375  return impl->dialectsRegistry;
376 }
377 
378 /// Return information about all registered IR dialects.
379 std::vector<Dialect *> MLIRContext::getLoadedDialects() {
380  std::vector<Dialect *> result;
381  result.reserve(impl->loadedDialects.size());
382  for (auto &dialect : impl->loadedDialects)
383  result.push_back(dialect.second.get());
384  llvm::array_pod_sort(result.begin(), result.end(),
385  [](Dialect *const *lhs, Dialect *const *rhs) -> int {
386  return (*lhs)->getNamespace() < (*rhs)->getNamespace();
387  });
388  return result;
389 }
390 std::vector<StringRef> MLIRContext::getAvailableDialects() {
391  std::vector<StringRef> result;
392  for (auto dialect : impl->dialectsRegistry.getDialectNames())
393  result.push_back(dialect);
394  return result;
395 }
396 
397 /// Get a registered IR dialect with the given namespace. If none is found,
398 /// then return nullptr.
400  // Dialects are sorted by name, so we can use binary search for lookup.
401  auto it = impl->loadedDialects.find(name);
402  return (it != impl->loadedDialects.end()) ? it->second.get() : nullptr;
403 }
404 
406  Dialect *dialect = getLoadedDialect(name);
407  if (dialect)
408  return dialect;
409  DialectAllocatorFunctionRef allocator =
410  impl->dialectsRegistry.getDialectAllocator(name);
411  return allocator ? allocator(this) : nullptr;
412 }
413 
414 /// Get a dialect for the provided namespace and TypeID: abort the program if a
415 /// dialect exist for this namespace with different TypeID. Returns a pointer to
416 /// the dialect owned by the context.
417 Dialect *
418 MLIRContext::getOrLoadDialect(StringRef dialectNamespace, TypeID dialectID,
419  function_ref<std::unique_ptr<Dialect>()> ctor) {
420  auto &impl = getImpl();
421  // Get the correct insertion position sorted by namespace.
422  auto dialectIt = impl.loadedDialects.find(dialectNamespace);
423 
424  if (dialectIt == impl.loadedDialects.end()) {
425  LLVM_DEBUG(llvm::dbgs()
426  << "Load new dialect in Context " << dialectNamespace << "\n");
427 #ifndef NDEBUG
428  if (impl.multiThreadedExecutionContext != 0)
429  llvm::report_fatal_error(
430  "Loading a dialect (" + dialectNamespace +
431  ") while in a multi-threaded execution context (maybe "
432  "the PassManager): this can indicate a "
433  "missing `dependentDialects` in a pass for example.");
434 #endif // NDEBUG
435  // loadedDialects entry is initialized to nullptr, indicating that the
436  // dialect is currently being loaded.
437  std::unique_ptr<Dialect> &dialect = impl.loadedDialects[dialectNamespace];
438  dialect = ctor();
439  assert(dialect && "dialect ctor failed");
440 
441  // Refresh all the identifiers dialect field, this catches cases where a
442  // dialect may be loaded after identifier prefixed with this dialect name
443  // were already created.
444  auto stringAttrsIt = impl.dialectReferencingStrAttrs.find(dialectNamespace);
445  if (stringAttrsIt != impl.dialectReferencingStrAttrs.end()) {
446  for (StringAttrStorage *storage : stringAttrsIt->second)
447  storage->referencedDialect = dialect.get();
448  impl.dialectReferencingStrAttrs.erase(stringAttrsIt);
449  }
450 
451  // Apply any extensions to this newly loaded dialect.
452  impl.dialectsRegistry.applyExtensions(dialect.get());
453  return dialect.get();
454  }
455 
456 #ifndef NDEBUG
457  if (dialectIt->second == nullptr)
458  llvm::report_fatal_error(
459  "Loading (and getting) a dialect (" + dialectNamespace +
460  ") while the same dialect is still loading: use loadDialect instead "
461  "of getOrLoadDialect.");
462 #endif // NDEBUG
463 
464  // Abort if dialect with namespace has already been registered.
465  std::unique_ptr<Dialect> &dialect = dialectIt->second;
466  if (dialect->getTypeID() != dialectID)
467  llvm::report_fatal_error("a dialect with namespace '" + dialectNamespace +
468  "' has already been registered");
469 
470  return dialect.get();
471 }
472 
473 bool MLIRContext::isDialectLoading(StringRef dialectNamespace) {
474  auto it = getImpl().loadedDialects.find(dialectNamespace);
475  // nullptr indicates that the dialect is currently being loaded.
476  return it != getImpl().loadedDialects.end() && it->second == nullptr;
477 }
478 
480  StringRef dialectNamespace, function_ref<void(DynamicDialect *)> ctor) {
481  auto &impl = getImpl();
482  // Get the correct insertion position sorted by namespace.
483  auto dialectIt = impl.loadedDialects.find(dialectNamespace);
484 
485  if (dialectIt != impl.loadedDialects.end()) {
486  if (auto *dynDialect = dyn_cast<DynamicDialect>(dialectIt->second.get()))
487  return dynDialect;
488  llvm::report_fatal_error("a dialect with namespace '" + dialectNamespace +
489  "' has already been registered");
490  }
491 
492  LLVM_DEBUG(llvm::dbgs() << "Load new dynamic dialect in Context "
493  << dialectNamespace << "\n");
494 #ifndef NDEBUG
495  if (impl.multiThreadedExecutionContext != 0)
496  llvm::report_fatal_error(
497  "Loading a dynamic dialect (" + dialectNamespace +
498  ") while in a multi-threaded execution context (maybe "
499  "the PassManager): this can indicate a "
500  "missing `dependentDialects` in a pass for example.");
501 #endif
502 
503  auto name = StringAttr::get(this, dialectNamespace);
504  auto *dialect = new DynamicDialect(name, this);
505  (void)getOrLoadDialect(name, dialect->getTypeID(), [dialect, ctor]() {
506  ctor(dialect);
507  return std::unique_ptr<DynamicDialect>(dialect);
508  });
509  // This is the same result as `getOrLoadDialect` (if it didn't failed),
510  // since it has the same TypeID, and TypeIDs are unique.
511  return dialect;
512 }
513 
515  for (StringRef name : getAvailableDialects())
516  getOrLoadDialect(name);
517 }
518 
519 llvm::hash_code MLIRContext::getRegistryHash() {
520  llvm::hash_code hash(0);
521  // Factor in number of loaded dialects, attributes, operations, types.
522  hash = llvm::hash_combine(hash, impl->loadedDialects.size());
523  hash = llvm::hash_combine(hash, impl->registeredAttributes.size());
524  hash = llvm::hash_combine(hash, impl->registeredOperations.size());
525  hash = llvm::hash_combine(hash, impl->registeredTypes.size());
526  return hash;
527 }
528 
530  return impl->allowUnregisteredDialects;
531 }
532 
534  assert(impl->multiThreadedExecutionContext == 0 &&
535  "changing MLIRContext `allow-unregistered-dialects` configuration "
536  "while in a multi-threaded execution context");
537  impl->allowUnregisteredDialects = allowing;
538 }
539 
540 /// Return true if multi-threading is enabled by the context.
542  return impl->threadingIsEnabled && llvm::llvm_is_multithreaded();
543 }
544 
545 /// Set the flag specifying if multi-threading is disabled by the context.
547  // This API can be overridden by the global debugging flag
548  // --mlir-disable-threading
550  return;
551  assert(impl->multiThreadedExecutionContext == 0 &&
552  "changing MLIRContext `disable-threading` configuration while "
553  "in a multi-threaded execution context");
554 
555  impl->threadingIsEnabled = !disable;
556 
557  // Update the threading mode for each of the uniquers.
558  impl->affineUniquer.disableMultithreading(disable);
559  impl->attributeUniquer.disableMultithreading(disable);
560  impl->typeUniquer.disableMultithreading(disable);
561 
562  // Destroy thread pool (stop all threads) if it is no longer needed, or create
563  // a new one if multithreading was re-enabled.
564  if (disable) {
565  // If the thread pool is owned, explicitly set it to nullptr to avoid
566  // keeping a dangling pointer around. If the thread pool is externally
567  // owned, we don't do anything.
568  if (impl->ownedThreadPool) {
569  assert(impl->threadPool);
570  impl->threadPool = nullptr;
571  impl->ownedThreadPool.reset();
572  }
573  } else if (!impl->threadPool) {
574  // The thread pool isn't externally provided.
575  assert(!impl->ownedThreadPool);
576  impl->ownedThreadPool = std::make_unique<llvm::ThreadPool>();
577  impl->threadPool = impl->ownedThreadPool.get();
578  }
579 }
580 
581 void MLIRContext::setThreadPool(llvm::ThreadPool &pool) {
582  assert(!isMultithreadingEnabled() &&
583  "expected multi-threading to be disabled when setting a ThreadPool");
584  impl->threadPool = &pool;
585  impl->ownedThreadPool.reset();
587 }
588 
590  if (isMultithreadingEnabled()) {
591  assert(impl->threadPool &&
592  "multi-threading is enabled but threadpool not set");
593  return impl->threadPool->getThreadCount();
594  }
595  // No multithreading or active thread pool. Return 1 thread.
596  return 1;
597 }
598 
599 llvm::ThreadPool &MLIRContext::getThreadPool() {
600  assert(isMultithreadingEnabled() &&
601  "expected multi-threading to be enabled within the context");
602  assert(impl->threadPool &&
603  "multi-threading is enabled but threadpool not set");
604  return *impl->threadPool;
605 }
606 
608 #ifndef NDEBUG
609  ++impl->multiThreadedExecutionContext;
610 #endif
611 }
613 #ifndef NDEBUG
614  --impl->multiThreadedExecutionContext;
615 #endif
616 }
617 
618 /// Return true if we should attach the operation to diagnostics emitted via
619 /// Operation::emit.
621  return impl->printOpOnDiagnostic;
622 }
623 
624 /// Set the flag specifying if we should attach the operation to diagnostics
625 /// emitted via Operation::emit.
627  assert(impl->multiThreadedExecutionContext == 0 &&
628  "changing MLIRContext `print-op-on-diagnostic` configuration while in "
629  "a multi-threaded execution context");
630  impl->printOpOnDiagnostic = enable;
631 }
632 
633 /// Return true if we should attach the current stacktrace to diagnostics when
634 /// emitted.
636  return impl->printStackTraceOnDiagnostic;
637 }
638 
639 /// Set the flag specifying if we should attach the current stacktrace when
640 /// emitting diagnostics.
642  assert(impl->multiThreadedExecutionContext == 0 &&
643  "changing MLIRContext `print-stacktrace-on-diagnostic` configuration "
644  "while in a multi-threaded execution context");
645  impl->printStackTraceOnDiagnostic = enable;
646 }
647 
648 /// Return information about all registered operations.
650  return impl->sortedRegisteredOperations;
651 }
652 
654  return RegisteredOperationName::lookup(name, this).has_value();
655 }
656 
657 void Dialect::addType(TypeID typeID, AbstractType &&typeInfo) {
658  auto &impl = context->getImpl();
659  assert(impl.multiThreadedExecutionContext == 0 &&
660  "Registering a new type kind while in a multi-threaded execution "
661  "context");
662  auto *newInfo =
663  new (impl.abstractDialectSymbolAllocator.Allocate<AbstractType>())
664  AbstractType(std::move(typeInfo));
665  if (!impl.registeredTypes.insert({typeID, newInfo}).second)
666  llvm::report_fatal_error("Dialect Type already registered.");
667 }
668 
669 void Dialect::addAttribute(TypeID typeID, AbstractAttribute &&attrInfo) {
670  auto &impl = context->getImpl();
671  assert(impl.multiThreadedExecutionContext == 0 &&
672  "Registering a new attribute kind while in a multi-threaded execution "
673  "context");
674  auto *newInfo =
675  new (impl.abstractDialectSymbolAllocator.Allocate<AbstractAttribute>())
676  AbstractAttribute(std::move(attrInfo));
677  if (!impl.registeredAttributes.insert({typeID, newInfo}).second)
678  llvm::report_fatal_error("Dialect Attribute already registered.");
679 }
680 
681 //===----------------------------------------------------------------------===//
682 // AbstractAttribute
683 //===----------------------------------------------------------------------===//
684 
685 /// Get the dialect that registered the attribute with the provided typeid.
687  MLIRContext *context) {
688  const AbstractAttribute *abstract = lookupMutable(typeID, context);
689  if (!abstract)
690  llvm::report_fatal_error("Trying to create an Attribute that was not "
691  "registered in this MLIRContext.");
692  return *abstract;
693 }
694 
695 AbstractAttribute *AbstractAttribute::lookupMutable(TypeID typeID,
696  MLIRContext *context) {
697  auto &impl = context->getImpl();
698  auto it = impl.registeredAttributes.find(typeID);
699  if (it == impl.registeredAttributes.end())
700  return nullptr;
701  return it->second;
702 }
703 
704 //===----------------------------------------------------------------------===//
705 // OperationName
706 //===----------------------------------------------------------------------===//
707 
708 OperationName::OperationName(StringRef name, MLIRContext *context) {
709  MLIRContextImpl &ctxImpl = context->getImpl();
710 
711  // Check for an existing name in read-only mode.
712  bool isMultithreadingEnabled = context->isMultithreadingEnabled();
713  if (isMultithreadingEnabled) {
714  // Check the registered info map first. In the overwhelmingly common case,
715  // the entry will be in here and it also removes the need to acquire any
716  // locks.
717  auto registeredIt = ctxImpl.registeredOperations.find(name);
718  if (LLVM_LIKELY(registeredIt != ctxImpl.registeredOperations.end())) {
719  impl = registeredIt->second.impl;
720  return;
721  }
722 
723  llvm::sys::SmartScopedReader<true> contextLock(ctxImpl.operationInfoMutex);
724  auto it = ctxImpl.operations.find(name);
725  if (it != ctxImpl.operations.end()) {
726  impl = &it->second;
727  return;
728  }
729  }
730 
731  // Acquire a writer-lock so that we can safely create the new instance.
732  ScopedWriterLock lock(ctxImpl.operationInfoMutex, isMultithreadingEnabled);
733 
734  auto it = ctxImpl.operations.insert({name, OperationName::Impl(nullptr)});
735  if (it.second)
736  it.first->second.name = StringAttr::get(context, name);
737  impl = &it.first->second;
738 }
739 
741  if (Dialect *dialect = getDialect())
742  return dialect->getNamespace();
743  return getStringRef().split('.').first;
744 }
745 
746 //===----------------------------------------------------------------------===//
747 // RegisteredOperationName
748 //===----------------------------------------------------------------------===//
749 
752  auto &impl = ctx->getImpl();
753  auto it = impl.registeredOperations.find(name);
754  if (it != impl.registeredOperations.end())
755  return it->getValue();
756  return llvm::None;
757 }
758 
761  OperationState &result) const {
762  return impl->parseAssemblyFn(parser, result);
763 }
764 
766  impl->populateDefaultAttrsFn(*this, attrs);
767 }
768 
770  StringRef name, Dialect &dialect, TypeID typeID,
771  ParseAssemblyFn &&parseAssembly, PrintAssemblyFn &&printAssembly,
772  VerifyInvariantsFn &&verifyInvariants,
773  VerifyRegionInvariantsFn &&verifyRegionInvariants, FoldHookFn &&foldHook,
774  GetCanonicalizationPatternsFn &&getCanonicalizationPatterns,
775  detail::InterfaceMap &&interfaceMap, HasTraitFn &&hasTrait,
776  ArrayRef<StringRef> attrNames,
777  PopulateDefaultAttrsFn &&populateDefaultAttrs) {
778  MLIRContext *ctx = dialect.getContext();
779  auto &ctxImpl = ctx->getImpl();
780  assert(ctxImpl.multiThreadedExecutionContext == 0 &&
781  "registering a new operation kind while in a multi-threaded execution "
782  "context");
783 
784  // Register the attribute names of this operation.
785  MutableArrayRef<StringAttr> cachedAttrNames;
786  if (!attrNames.empty()) {
787  cachedAttrNames = MutableArrayRef<StringAttr>(
788  ctxImpl.abstractDialectSymbolAllocator.Allocate<StringAttr>(
789  attrNames.size()),
790  attrNames.size());
791  for (unsigned i : llvm::seq<unsigned>(0, attrNames.size()))
792  new (&cachedAttrNames[i]) StringAttr(StringAttr::get(ctx, attrNames[i]));
793  }
794 
795  // Insert the operation info if it doesn't exist yet.
796  auto it = ctxImpl.operations.insert({name, OperationName::Impl(nullptr)});
797  if (it.second)
798  it.first->second.name = StringAttr::get(ctx, name);
799  OperationName::Impl &impl = it.first->second;
800 
801  if (impl.isRegistered()) {
802  llvm::errs() << "error: operation named '" << name
803  << "' is already registered.\n";
804  abort();
805  }
806  auto emplaced = ctxImpl.registeredOperations.try_emplace(
807  name, RegisteredOperationName(&impl));
808  assert(emplaced.second && "operation name registration must be successful");
809 
810  // Add emplaced operation name to the sorted operations container.
811  RegisteredOperationName &value = emplaced.first->getValue();
812  ctxImpl.sortedRegisteredOperations.insert(
813  llvm::upper_bound(ctxImpl.sortedRegisteredOperations, value,
814  [](auto &lhs, auto &rhs) {
815  return lhs.getIdentifier().compare(
816  rhs.getIdentifier());
817  }),
818  value);
819 
820  // Update the registered info for this operation.
821  impl.dialect = &dialect;
822  impl.typeID = typeID;
823  impl.interfaceMap = std::move(interfaceMap);
824  impl.foldHookFn = std::move(foldHook);
825  impl.getCanonicalizationPatternsFn = std::move(getCanonicalizationPatterns);
826  impl.hasTraitFn = std::move(hasTrait);
827  impl.parseAssemblyFn = std::move(parseAssembly);
828  impl.printAssemblyFn = std::move(printAssembly);
829  impl.verifyInvariantsFn = std::move(verifyInvariants);
830  impl.verifyRegionInvariantsFn = std::move(verifyRegionInvariants);
831  impl.attributeNames = cachedAttrNames;
832  impl.populateDefaultAttrsFn = std::move(populateDefaultAttrs);
833 }
834 
835 //===----------------------------------------------------------------------===//
836 // AbstractType
837 //===----------------------------------------------------------------------===//
838 
840  const AbstractType *type = lookupMutable(typeID, context);
841  if (!type)
842  llvm::report_fatal_error(
843  "Trying to create a Type that was not registered in this MLIRContext.");
844  return *type;
845 }
846 
847 AbstractType *AbstractType::lookupMutable(TypeID typeID, MLIRContext *context) {
848  auto &impl = context->getImpl();
849  auto it = impl.registeredTypes.find(typeID);
850  if (it == impl.registeredTypes.end())
851  return nullptr;
852  return it->second;
853 }
854 
855 //===----------------------------------------------------------------------===//
856 // Type uniquing
857 //===----------------------------------------------------------------------===//
858 
859 /// Returns the storage uniquer used for constructing type storage instances.
860 /// This should not be used directly.
862 
863 Float8E5M2Type Float8E5M2Type::get(MLIRContext *context) {
864  return context->getImpl().f8E5M2Ty;
865 }
866 Float8E4M3FNType Float8E4M3FNType::get(MLIRContext *context) {
867  return context->getImpl().f8E4M3FNTy;
868 }
869 BFloat16Type BFloat16Type::get(MLIRContext *context) {
870  return context->getImpl().bf16Ty;
871 }
872 Float16Type Float16Type::get(MLIRContext *context) {
873  return context->getImpl().f16Ty;
874 }
875 Float32Type Float32Type::get(MLIRContext *context) {
876  return context->getImpl().f32Ty;
877 }
878 Float64Type Float64Type::get(MLIRContext *context) {
879  return context->getImpl().f64Ty;
880 }
881 Float80Type Float80Type::get(MLIRContext *context) {
882  return context->getImpl().f80Ty;
883 }
884 Float128Type Float128Type::get(MLIRContext *context) {
885  return context->getImpl().f128Ty;
886 }
887 
888 /// Get an instance of the IndexType.
889 IndexType IndexType::get(MLIRContext *context) {
890  return context->getImpl().indexTy;
891 }
892 
893 /// Return an existing integer type instance if one is cached within the
894 /// context.
895 static IntegerType
896 getCachedIntegerType(unsigned width,
897  IntegerType::SignednessSemantics signedness,
898  MLIRContext *context) {
899  if (signedness != IntegerType::Signless)
900  return IntegerType();
901 
902  switch (width) {
903  case 1:
904  return context->getImpl().int1Ty;
905  case 8:
906  return context->getImpl().int8Ty;
907  case 16:
908  return context->getImpl().int16Ty;
909  case 32:
910  return context->getImpl().int32Ty;
911  case 64:
912  return context->getImpl().int64Ty;
913  case 128:
914  return context->getImpl().int128Ty;
915  default:
916  return IntegerType();
917  }
918 }
919 
920 IntegerType IntegerType::get(MLIRContext *context, unsigned width,
921  IntegerType::SignednessSemantics signedness) {
922  if (auto cached = getCachedIntegerType(width, signedness, context))
923  return cached;
924  return Base::get(context, width, signedness);
925 }
926 
927 IntegerType
928 IntegerType::getChecked(function_ref<InFlightDiagnostic()> emitError,
929  MLIRContext *context, unsigned width,
930  SignednessSemantics signedness) {
931  if (auto cached = getCachedIntegerType(width, signedness, context))
932  return cached;
933  return Base::getChecked(emitError, context, width, signedness);
934 }
935 
936 /// Get an instance of the NoneType.
937 NoneType NoneType::get(MLIRContext *context) {
938  if (NoneType cachedInst = context->getImpl().noneType)
939  return cachedInst;
940  // Note: May happen when initializing the singleton attributes of the builtin
941  // dialect.
942  return Base::get(context);
943 }
944 
945 //===----------------------------------------------------------------------===//
946 // Attribute uniquing
947 //===----------------------------------------------------------------------===//
948 
949 /// Returns the storage uniquer used for constructing attribute storage
950 /// instances. This should not be used directly.
952  return getImpl().attributeUniquer;
953 }
954 
955 /// Initialize the given attribute storage instance.
956 void AttributeUniquer::initializeAttributeStorage(AttributeStorage *storage,
957  MLIRContext *ctx,
958  TypeID attrID) {
960 }
961 
963  return value ? context->getImpl().trueAttr : context->getImpl().falseAttr;
964 }
965 
966 UnitAttr UnitAttr::get(MLIRContext *context) {
967  return context->getImpl().unitAttr;
968 }
969 
970 UnknownLoc UnknownLoc::get(MLIRContext *context) {
971  return context->getImpl().unknownLocAttr;
972 }
973 
974 /// Return empty dictionary.
975 DictionaryAttr DictionaryAttr::getEmpty(MLIRContext *context) {
976  return context->getImpl().emptyDictionaryAttr;
977 }
978 
979 void StringAttrStorage::initialize(MLIRContext *context) {
980  // Check for a dialect namespace prefix, if there isn't one we don't need to
981  // do any additional initialization.
982  auto dialectNamePair = value.split('.');
983  if (dialectNamePair.first.empty() || dialectNamePair.second.empty())
984  return;
985 
986  // If one exists, we check to see if this dialect is loaded. If it is, we set
987  // the dialect now, if it isn't we record this storage for initialization
988  // later if the dialect ever gets loaded.
989  if ((referencedDialect = context->getLoadedDialect(dialectNamePair.first)))
990  return;
991 
992  MLIRContextImpl &impl = context->getImpl();
993  llvm::sys::SmartScopedLock<true> lock(impl.dialectRefStrAttrMutex);
994  impl.dialectReferencingStrAttrs[dialectNamePair.first].push_back(this);
995 }
996 
997 /// Return an empty string.
998 StringAttr StringAttr::get(MLIRContext *context) {
999  return context->getImpl().emptyStringAttr;
1000 }
1001 
1002 //===----------------------------------------------------------------------===//
1003 // AffineMap uniquing
1004 //===----------------------------------------------------------------------===//
1005 
1007  return getImpl().affineUniquer;
1008 }
1009 
1010 AffineMap AffineMap::getImpl(unsigned dimCount, unsigned symbolCount,
1011  ArrayRef<AffineExpr> results,
1012  MLIRContext *context) {
1013  auto &impl = context->getImpl();
1014  auto *storage = impl.affineUniquer.get<AffineMapStorage>(
1015  [&](AffineMapStorage *storage) { storage->context = context; }, dimCount,
1016  symbolCount, results);
1017  return AffineMap(storage);
1018 }
1019 
1020 /// Check whether the arguments passed to the AffineMap::get() are consistent.
1021 /// This method checks whether the highest index of dimensional identifier
1022 /// present in result expressions is less than `dimCount` and the highest index
1023 /// of symbolic identifier present in result expressions is less than
1024 /// `symbolCount`.
1025 LLVM_ATTRIBUTE_UNUSED static bool
1026 willBeValidAffineMap(unsigned dimCount, unsigned symbolCount,
1027  ArrayRef<AffineExpr> results) {
1028  int64_t maxDimPosition = -1;
1029  int64_t maxSymbolPosition = -1;
1030  getMaxDimAndSymbol(ArrayRef<ArrayRef<AffineExpr>>(results), maxDimPosition,
1031  maxSymbolPosition);
1032  if ((maxDimPosition >= dimCount) || (maxSymbolPosition >= symbolCount)) {
1033  LLVM_DEBUG(
1034  llvm::dbgs()
1035  << "maximum dimensional identifier position in result expression must "
1036  "be less than `dimCount` and maximum symbolic identifier position "
1037  "in result expression must be less than `symbolCount`\n");
1038  return false;
1039  }
1040  return true;
1041 }
1042 
1044  return getImpl(/*dimCount=*/0, /*symbolCount=*/0, /*results=*/{}, context);
1045 }
1046 
1047 AffineMap AffineMap::get(unsigned dimCount, unsigned symbolCount,
1048  MLIRContext *context) {
1049  return getImpl(dimCount, symbolCount, /*results=*/{}, context);
1050 }
1051 
1052 AffineMap AffineMap::get(unsigned dimCount, unsigned symbolCount,
1053  AffineExpr result) {
1054  assert(willBeValidAffineMap(dimCount, symbolCount, {result}));
1055  return getImpl(dimCount, symbolCount, {result}, result.getContext());
1056 }
1057 
1058 AffineMap AffineMap::get(unsigned dimCount, unsigned symbolCount,
1059  ArrayRef<AffineExpr> results, MLIRContext *context) {
1060  assert(willBeValidAffineMap(dimCount, symbolCount, results));
1061  return getImpl(dimCount, symbolCount, results, context);
1062 }
1063 
1064 //===----------------------------------------------------------------------===//
1065 // Integer Sets: these are allocated into the bump pointer, and are immutable.
1066 // Unlike AffineMap's, these are uniqued only if they are small.
1067 //===----------------------------------------------------------------------===//
1068 
1069 IntegerSet IntegerSet::get(unsigned dimCount, unsigned symbolCount,
1070  ArrayRef<AffineExpr> constraints,
1071  ArrayRef<bool> eqFlags) {
1072  // The number of constraints can't be zero.
1073  assert(!constraints.empty());
1074  assert(constraints.size() == eqFlags.size());
1075 
1076  auto &impl = constraints[0].getContext()->getImpl();
1077  auto *storage = impl.affineUniquer.get<IntegerSetStorage>(
1078  [](IntegerSetStorage *) {}, dimCount, symbolCount, constraints, eqFlags);
1079  return IntegerSet(storage);
1080 }
1081 
1082 //===----------------------------------------------------------------------===//
1083 // StorageUniquerSupport
1084 //===----------------------------------------------------------------------===//
1085 
1086 /// Utility method to generate a callback that can be used to generate a
1087 /// diagnostic when checking the construction invariants of a storage object.
1088 /// This is defined out-of-line to avoid the need to include Location.h.
1089 llvm::unique_function<InFlightDiagnostic()>
1091  return [ctx] { return emitError(UnknownLoc::get(ctx)); };
1092 }
1093 llvm::unique_function<InFlightDiagnostic()>
1095  return [=] { return emitError(loc); };
1096 }
static constexpr const bool value
static LLVM_ATTRIBUTE_UNUSED bool willBeValidAffineMap(unsigned dimCount, unsigned symbolCount, ArrayRef< AffineExpr > results)
Check whether the arguments passed to the AffineMap::get() are consistent.
static bool isThreadingGloballyDisabled()
Definition: MLIRContext.cpp:75
static ArrayRef< T > copyArrayRefInto(llvm::BumpPtrAllocator &allocator, ArrayRef< T > elements)
Copy the specified array of elements into memory managed by the provided bump pointer allocator.
static llvm::ManagedStatic< MLIRContextOptions > clOptions
Definition: MLIRContext.cpp:73
static IntegerType getCachedIntegerType(unsigned width, IntegerType::SignednessSemantics signedness, MLIRContext *context)
Return an existing integer type instance if one is cached within the context.
This class contains all of the static information common to all instances of a registered Attribute.
static const AbstractAttribute & lookup(TypeID typeID, MLIRContext *context)
Look up the specified abstract attribute in the MLIRContext and return a reference to it.
This class contains all of the static information common to all instances of a registered Type.
Definition: TypeSupport.h:30
static const AbstractType & lookup(TypeID typeID, MLIRContext *context)
Look up the specified abstract type in the MLIRContext and return a reference to it.
Base type for affine expression.
Definition: AffineExpr.h:68
MLIRContext * getContext() const
Definition: AffineExpr.cpp:24
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition: AffineMap.h:42
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
constexpr AffineMap()=default
Base storage class appearing in an attribute.
void initializeAbstractAttribute(const AbstractAttribute &abstractAttr)
Set the abstract attribute for this storage instance.
Special case of IntegerAttr to represent boolean integers, i.e., signless i1 integers.
static BoolAttr get(MLIRContext *context, bool value)
This class represents manages debug actions, and orchestrates the communication between action querie...
Definition: DebugAction.h:43
This class is the main interface for diagnostics.
Definition: Diagnostics.h:407
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool isSubsetOf(const DialectRegistry &rhs) const
Returns true if the current registry is a subset of 'rhs', i.e.
Definition: Dialect.cpp:255
void appendTo(DialectRegistry &destination) const
void applyExtensions(Dialect *dialect) const
Apply any held extensions that require the given dialect.
Definition: Dialect.cpp:189
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:41
MLIRContext * getContext() const
Definition: Dialect.h:55
A dialect that can be defined at runtime.
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:307
An integer set representing a conjunction of one or more affine equalities and inequalities.
Definition: IntegerSet.h:44
constexpr IntegerSet()=default
static IntegerSet get(unsigned dimCount, unsigned symbolCount, ArrayRef< AffineExpr > constraints, ArrayRef< bool > eqFlags)
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:64
This is the implementation of the MLIRContext class, using the pImpl idiom.
DictionaryAttr emptyDictionaryAttr
DenseMap< StringRef, std::unique_ptr< Dialect > > loadedDialects
This is a list of dialects that are created referring to this context.
BoolAttr falseAttr
Cached Attribute Instances.
llvm::sys::SmartRWMutex< true > operationInfoMutex
A mutex used when accessing operation information.
DenseMap< StringRef, SmallVector< StringAttrStorage * > > dialectReferencingStrAttrs
StringAttr emptyStringAttr
llvm::sys::SmartMutex< true > dialectRefStrAttrMutex
Map of string attributes that may reference a dialect, that are awaiting that dialect to be loaded.
StorageUniquer typeUniquer
DebugActionManager debugActionManager
An action manager for use within the context.
llvm::BumpPtrAllocator abstractDialectSymbolAllocator
An allocator used for AbstractAttribute and AbstractType objects.
DenseMap< TypeID, AbstractType * > registeredTypes
Float8E5M2Type f8E5M2Ty
Cached Type Instances.
StorageUniquer affineUniquer
DiagnosticEngine diagEngine
DenseMap< TypeID, AbstractAttribute * > registeredAttributes
llvm::StringMap< OperationName::Impl > operations
This is a mapping from operation name to the operation info describing it.
llvm::StringMap< RegisteredOperationName > registeredOperations
A vector of operation info specifically for registered operations.
SmallVector< RegisteredOperationName, 0 > sortedRegisteredOperations
This is a sorted container of registered operations for a deterministic and efficient getRegisteredOp...
Float8E4M3FNType f8E4M3FNTy
MLIRContextImpl(bool threadingIsEnabled)
std::unique_ptr< llvm::ThreadPool > ownedThreadPool
In case where the thread pool is owned by the context, this ensures destruction with the context.
StorageUniquer attributeUniquer
DialectRegistry dialectsRegistry
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:56
DebugActionManager & getDebugActionManager()
Returns the manager of debug actions within the context.
void appendDialectRegistry(const DialectRegistry &registry)
Append the contents of the given dialect registry to the registry associated with this context.
bool shouldPrintStackTraceOnDiagnostic()
Return true if we should attach the current stacktrace to diagnostics when emitted.
unsigned getNumThreads()
Return the number of threads used by the thread pool in this context.
bool isOperationRegistered(StringRef name)
Return true if this operation name is registered in this context.
MLIRContext(Threading multithreading=Threading::ENABLED)
Create a new Context.
void disableMultithreading(bool disable=true)
Set the flag specifying if multi-threading is disabled by the context.
void printStackTraceOnDiagnostic(bool enable)
Set the flag specifying if we should attach the current stacktrace when emitting diagnostics.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
void setThreadPool(llvm::ThreadPool &pool)
Set a new thread pool to be used in this context.
void enableMultithreading(bool enable=true)
Definition: MLIRContext.h:144
std::vector< Dialect * > getLoadedDialects()
Return information about all IR dialects loaded in the context.
void printOpOnDiagnostic(bool enable)
Set the flag specifying if we should attach the operation to diagnostics emitted via Operation::emit.
ArrayRef< RegisteredOperationName > getRegisteredOperations()
Return a sorted array containing the information about all registered operations.
llvm::hash_code getRegistryHash()
Returns a hash of the registry of the context that may be used to give a rough indicator of if the st...
void enterMultiThreadedExecution()
These APIs are tracking whether the context will be used in a multithreading environment: this has no...
const DialectRegistry & getDialectRegistry()
Return the dialect registry associated with this context.
DynamicDialect * getOrLoadDynamicDialect(StringRef dialectNamespace, function_ref< void(DynamicDialect *)> ctor)
Get (or create) a dynamic dialect for the given name.
StorageUniquer & getAttributeUniquer()
Returns the storage uniquer used for constructing attribute storage instances.
StorageUniquer & getAffineUniquer()
Returns the storage uniquer used for creating affine constructs.
llvm::ThreadPool & getThreadPool()
Return the thread pool used by this context.
StorageUniquer & getTypeUniquer()
Returns the storage uniquer used for constructing type storage instances.
std::vector< StringRef > getAvailableDialects()
Return information about all available dialects in the registry in 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.
T * getLoadedDialect()
Get a registered IR dialect for the given derived dialect type.
Definition: MLIRContext.h:86
DiagnosticEngine & getDiagEngine()
Returns the diagnostic engine for this context.
MLIRContextImpl & getImpl()
Definition: MLIRContext.h:197
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
Definition: MLIRContext.h:93
void exitMultiThreadedExecution()
bool shouldPrintOpOnDiagnostic()
Return true if we should attach the operation to diagnostics emitted via Operation::emit.
void loadAllAvailableDialects()
Load all dialects available in the registry in this context.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
llvm::unique_function< LogicalResult(Operation *) const > VerifyInvariantsFn
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
llvm::unique_function< bool(TypeID) const > HasTraitFn
Dialect * getDialect() const
Return the dialect this operation is registered to if the dialect is loaded in the context,...
OperationName(StringRef name, MLIRContext *context)
StringRef getDialectNamespace() const
Return the name of the dialect this operation is registered to.
llvm::unique_function< LogicalResult(Operation *) const > VerifyRegionInvariantsFn
llvm::unique_function< void(Operation *, OpAsmPrinter &, StringRef) const > PrintAssemblyFn
llvm::unique_function< LogicalResult(Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &) const > FoldHookFn
llvm::unique_function< ParseResult(OpAsmParser &, OperationState &) const > ParseAssemblyFn
llvm::unique_function< void(RewritePatternSet &, MLIRContext *) const > GetCanonicalizationPatternsFn
llvm::unique_function< void(const RegisteredOperationName &, NamedAttrList &) const > PopulateDefaultAttrsFn
This class represents success/failure for parsing-like operations that find it important to chain tog...
This is a "type erased" representation of a registered operation.
static void insert(Dialect &dialect)
Register a new operation in a Dialect object.
void populateDefaultAttrs(NamedAttrList &attrs) const
This hook implements the method to populate defaults attributes that are unset.
ParseResult parseAssembly(OpAsmParser &parser, OperationState &result) const
Use the specified object to parse this ops custom assembly format.
LogicalResult foldHook(Operation *op, ArrayRef< Attribute > operands, SmallVectorImpl< OpFoldResult > &results) const
This hook implements a generalized folder for this operation.
void getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) const
This hook returns any canonicalization pattern rewrites that the operation supports,...
bool hasTrait() const
Returns true if the operation has a particular trait.
LogicalResult verifyInvariants(Operation *op) const
These hooks implement the verifiers for this operation.
static Optional< RegisteredOperationName > lookup(StringRef name, MLIRContext *ctx)
Lookup the registered operation information for the given operation.
LogicalResult verifyRegionInvariants(Operation *op) const
void printAssembly(Operation *op, OpAsmPrinter &p, StringRef defaultDialect) const
This hook implements the AsmPrinter for this operation.
A utility class to get or create instances of "storage classes".
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:104
This class provides an efficient mapping between a given Interface type, and a particular implementat...
Detect if any of the given parameter types has a sub-element handler.
llvm::unique_function< InFlightDiagnostic()> getDefaultDiagnosticEmitFn(MLIRContext *ctx)
Utility method to generate a callback that can be used to generate a diagnostic when checking the con...
static bool hasTrait(TypeID traitID)
Returns true if this given Trait ID matches the IDs of any of the provided trait types Traits.
Include the generated interface declarations.
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:86
static void getMaxDimAndSymbol(ArrayRef< AffineExprContainer > exprsList, int64_t &maxDim, int64_t &maxSym)
Calculates maxmimum dimension and symbol positions from the expressions in exprsLists and stores them...
Definition: AffineMap.h:585
This class represents a type erased version of an operation.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
A binary operation appearing in an affine expression.
An integer constant appearing in affine expression.
A dimensional or symbolic identifier appearing in an affine expression.
Dialect * referencedDialect
If the string value contains a dialect namespace prefix (e.g.