MLIR  19.0.0git
ModuleTranslation.cpp
Go to the documentation of this file.
1 //===- ModuleTranslation.cpp - MLIR to LLVM conversion --------------------===//
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 file implements the translation between an MLIR LLVM dialect module and
10 // the corresponding LLVMIR module. It only handles core LLVM IR operations.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 
16 #include "AttrKindDetail.h"
17 #include "DebugTranslation.h"
20 #include "mlir/Dialect/DLTI/DLTI.h"
28 #include "mlir/IR/Attributes.h"
29 #include "mlir/IR/BuiltinOps.h"
30 #include "mlir/IR/BuiltinTypes.h"
33 #include "mlir/Support/LLVM.h"
37 
38 #include "llvm/ADT/PostOrderIterator.h"
39 #include "llvm/ADT/SetVector.h"
40 #include "llvm/ADT/StringExtras.h"
41 #include "llvm/ADT/TypeSwitch.h"
42 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
43 #include "llvm/IR/BasicBlock.h"
44 #include "llvm/IR/CFG.h"
45 #include "llvm/IR/Constants.h"
46 #include "llvm/IR/DerivedTypes.h"
47 #include "llvm/IR/IRBuilder.h"
48 #include "llvm/IR/InlineAsm.h"
49 #include "llvm/IR/IntrinsicsNVPTX.h"
50 #include "llvm/IR/LLVMContext.h"
51 #include "llvm/IR/MDBuilder.h"
52 #include "llvm/IR/Module.h"
53 #include "llvm/IR/Verifier.h"
54 #include "llvm/Support/Debug.h"
55 #include "llvm/Support/raw_ostream.h"
56 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
57 #include "llvm/Transforms/Utils/Cloning.h"
58 #include "llvm/Transforms/Utils/ModuleUtils.h"
59 #include <optional>
60 
61 #define DEBUG_TYPE "llvm-dialect-to-llvm-ir"
62 
63 using namespace mlir;
64 using namespace mlir::LLVM;
65 using namespace mlir::LLVM::detail;
66 
67 extern llvm::cl::opt<bool> UseNewDbgInfoFormat;
68 
69 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
70 
71 namespace {
72 /// A customized inserter for LLVM's IRBuilder that captures all LLVM IR
73 /// instructions that are created for future reference.
74 ///
75 /// This is intended to be used with the `CollectionScope` RAII object:
76 ///
77 /// llvm::IRBuilder<..., InstructionCapturingInserter> builder;
78 /// {
79 /// InstructionCapturingInserter::CollectionScope scope(builder);
80 /// // Call IRBuilder methods as usual.
81 ///
82 /// // This will return a list of all instructions created by the builder,
83 /// // in order of creation.
84 /// builder.getInserter().getCapturedInstructions();
85 /// }
86 /// // This will return an empty list.
87 /// builder.getInserter().getCapturedInstructions();
88 ///
89 /// The capturing functionality is _disabled_ by default for performance
90 /// consideration. It needs to be explicitly enabled, which is achieved by
91 /// creating a `CollectionScope`.
92 class InstructionCapturingInserter : public llvm::IRBuilderCallbackInserter {
93 public:
94  /// Constructs the inserter.
95  InstructionCapturingInserter()
96  : llvm::IRBuilderCallbackInserter([this](llvm::Instruction *instruction) {
97  if (LLVM_LIKELY(enabled))
98  capturedInstructions.push_back(instruction);
99  }) {}
100 
101  /// Returns the list of LLVM IR instructions captured since the last cleanup.
102  ArrayRef<llvm::Instruction *> getCapturedInstructions() const {
103  return capturedInstructions;
104  }
105 
106  /// Clears the list of captured LLVM IR instructions.
107  void clearCapturedInstructions() { capturedInstructions.clear(); }
108 
109  /// RAII object enabling the capture of created LLVM IR instructions.
110  class CollectionScope {
111  public:
112  /// Creates the scope for the given inserter.
113  CollectionScope(llvm::IRBuilderBase &irBuilder, bool isBuilderCapturing);
114 
115  /// Ends the scope.
116  ~CollectionScope();
117 
118  ArrayRef<llvm::Instruction *> getCapturedInstructions() {
119  if (!inserter)
120  return {};
121  return inserter->getCapturedInstructions();
122  }
123 
124  private:
125  /// Back reference to the inserter.
126  InstructionCapturingInserter *inserter = nullptr;
127 
128  /// List of instructions in the inserter prior to this scope.
129  SmallVector<llvm::Instruction *> previouslyCollectedInstructions;
130 
131  /// Whether the inserter was enabled prior to this scope.
132  bool wasEnabled;
133  };
134 
135  /// Enable or disable the capturing mechanism.
136  void setEnabled(bool enabled = true) { this->enabled = enabled; }
137 
138 private:
139  /// List of captured instructions.
140  SmallVector<llvm::Instruction *> capturedInstructions;
141 
142  /// Whether the collection is enabled.
143  bool enabled = false;
144 };
145 
146 using CapturingIRBuilder =
147  llvm::IRBuilder<llvm::ConstantFolder, InstructionCapturingInserter>;
148 } // namespace
149 
150 InstructionCapturingInserter::CollectionScope::CollectionScope(
151  llvm::IRBuilderBase &irBuilder, bool isBuilderCapturing) {
152 
153  if (!isBuilderCapturing)
154  return;
155 
156  auto &capturingIRBuilder = static_cast<CapturingIRBuilder &>(irBuilder);
157  inserter = &capturingIRBuilder.getInserter();
158  wasEnabled = inserter->enabled;
159  if (wasEnabled)
160  previouslyCollectedInstructions.swap(inserter->capturedInstructions);
161  inserter->setEnabled(true);
162 }
163 
164 InstructionCapturingInserter::CollectionScope::~CollectionScope() {
165  if (!inserter)
166  return;
167 
168  previouslyCollectedInstructions.swap(inserter->capturedInstructions);
169  // If collection was enabled (likely in another, surrounding scope), keep
170  // the instructions collected in this scope.
171  if (wasEnabled) {
172  llvm::append_range(inserter->capturedInstructions,
173  previouslyCollectedInstructions);
174  }
175  inserter->setEnabled(wasEnabled);
176 }
177 
178 /// Translates the given data layout spec attribute to the LLVM IR data layout.
179 /// Only integer, float, pointer and endianness entries are currently supported.
181 translateDataLayout(DataLayoutSpecInterface attribute,
182  const DataLayout &dataLayout,
183  std::optional<Location> loc = std::nullopt) {
184  if (!loc)
185  loc = UnknownLoc::get(attribute.getContext());
186 
187  // Translate the endianness attribute.
188  std::string llvmDataLayout;
189  llvm::raw_string_ostream layoutStream(llvmDataLayout);
190  for (DataLayoutEntryInterface entry : attribute.getEntries()) {
191  auto key = llvm::dyn_cast_if_present<StringAttr>(entry.getKey());
192  if (!key)
193  continue;
194  if (key.getValue() == DLTIDialect::kDataLayoutEndiannessKey) {
195  auto value = cast<StringAttr>(entry.getValue());
196  bool isLittleEndian =
197  value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle;
198  layoutStream << "-" << (isLittleEndian ? "e" : "E");
199  layoutStream.flush();
200  continue;
201  }
202  if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
203  auto value = cast<IntegerAttr>(entry.getValue());
204  uint64_t space = value.getValue().getZExtValue();
205  // Skip the default address space.
206  if (space == 0)
207  continue;
208  layoutStream << "-P" << space;
209  layoutStream.flush();
210  continue;
211  }
212  if (key.getValue() == DLTIDialect::kDataLayoutGlobalMemorySpaceKey) {
213  auto value = cast<IntegerAttr>(entry.getValue());
214  uint64_t space = value.getValue().getZExtValue();
215  // Skip the default address space.
216  if (space == 0)
217  continue;
218  layoutStream << "-G" << space;
219  layoutStream.flush();
220  continue;
221  }
222  if (key.getValue() == DLTIDialect::kDataLayoutAllocaMemorySpaceKey) {
223  auto value = cast<IntegerAttr>(entry.getValue());
224  uint64_t space = value.getValue().getZExtValue();
225  // Skip the default address space.
226  if (space == 0)
227  continue;
228  layoutStream << "-A" << space;
229  layoutStream.flush();
230  continue;
231  }
232  if (key.getValue() == DLTIDialect::kDataLayoutStackAlignmentKey) {
233  auto value = cast<IntegerAttr>(entry.getValue());
234  uint64_t alignment = value.getValue().getZExtValue();
235  // Skip the default stack alignment.
236  if (alignment == 0)
237  continue;
238  layoutStream << "-S" << alignment;
239  layoutStream.flush();
240  continue;
241  }
242  emitError(*loc) << "unsupported data layout key " << key;
243  return failure();
244  }
245 
246  // Go through the list of entries to check which types are explicitly
247  // specified in entries. Where possible, data layout queries are used instead
248  // of directly inspecting the entries.
249  for (DataLayoutEntryInterface entry : attribute.getEntries()) {
250  auto type = llvm::dyn_cast_if_present<Type>(entry.getKey());
251  if (!type)
252  continue;
253  // Data layout for the index type is irrelevant at this point.
254  if (isa<IndexType>(type))
255  continue;
256  layoutStream << "-";
257  LogicalResult result =
259  .Case<IntegerType, Float16Type, Float32Type, Float64Type,
260  Float80Type, Float128Type>([&](Type type) -> LogicalResult {
261  if (auto intType = dyn_cast<IntegerType>(type)) {
262  if (intType.getSignedness() != IntegerType::Signless)
263  return emitError(*loc)
264  << "unsupported data layout for non-signless integer "
265  << intType;
266  layoutStream << "i";
267  } else {
268  layoutStream << "f";
269  }
270  uint64_t size = dataLayout.getTypeSizeInBits(type);
271  uint64_t abi = dataLayout.getTypeABIAlignment(type) * 8u;
272  uint64_t preferred =
273  dataLayout.getTypePreferredAlignment(type) * 8u;
274  layoutStream << size << ":" << abi;
275  if (abi != preferred)
276  layoutStream << ":" << preferred;
277  return success();
278  })
279  .Case([&](LLVMPointerType type) {
280  layoutStream << "p" << type.getAddressSpace() << ":";
281  uint64_t size = dataLayout.getTypeSizeInBits(type);
282  uint64_t abi = dataLayout.getTypeABIAlignment(type) * 8u;
283  uint64_t preferred =
284  dataLayout.getTypePreferredAlignment(type) * 8u;
285  uint64_t index = *dataLayout.getTypeIndexBitwidth(type);
286  layoutStream << size << ":" << abi << ":" << preferred << ":"
287  << index;
288  return success();
289  })
290  .Default([loc](Type type) {
291  return emitError(*loc)
292  << "unsupported type in data layout: " << type;
293  });
294  if (failed(result))
295  return failure();
296  }
297  layoutStream.flush();
298  StringRef layoutSpec(llvmDataLayout);
299  if (layoutSpec.starts_with("-"))
300  layoutSpec = layoutSpec.drop_front();
301 
302  return llvm::DataLayout(layoutSpec);
303 }
304 
305 /// Builds a constant of a sequential LLVM type `type`, potentially containing
306 /// other sequential types recursively, from the individual constant values
307 /// provided in `constants`. `shape` contains the number of elements in nested
308 /// sequential types. Reports errors at `loc` and returns nullptr on error.
309 static llvm::Constant *
311  ArrayRef<int64_t> shape, llvm::Type *type,
312  Location loc) {
313  if (shape.empty()) {
314  llvm::Constant *result = constants.front();
315  constants = constants.drop_front();
316  return result;
317  }
318 
319  llvm::Type *elementType;
320  if (auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
321  elementType = arrayTy->getElementType();
322  } else if (auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
323  elementType = vectorTy->getElementType();
324  } else {
325  emitError(loc) << "expected sequential LLVM types wrapping a scalar";
326  return nullptr;
327  }
328 
330  nested.reserve(shape.front());
331  for (int64_t i = 0; i < shape.front(); ++i) {
332  nested.push_back(buildSequentialConstant(constants, shape.drop_front(),
333  elementType, loc));
334  if (!nested.back())
335  return nullptr;
336  }
337 
338  if (shape.size() == 1 && type->isVectorTy())
339  return llvm::ConstantVector::get(nested);
341  llvm::ArrayType::get(elementType, shape.front()), nested);
342 }
343 
344 /// Returns the first non-sequential type nested in sequential types.
345 static llvm::Type *getInnermostElementType(llvm::Type *type) {
346  do {
347  if (auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
348  type = arrayTy->getElementType();
349  } else if (auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
350  type = vectorTy->getElementType();
351  } else {
352  return type;
353  }
354  } while (true);
355 }
356 
357 /// Convert a dense elements attribute to an LLVM IR constant using its raw data
358 /// storage if possible. This supports elements attributes of tensor or vector
359 /// type and avoids constructing separate objects for individual values of the
360 /// innermost dimension. Constants for other dimensions are still constructed
361 /// recursively. Returns null if constructing from raw data is not supported for
362 /// this type, e.g., element type is not a power-of-two-sized primitive. Reports
363 /// other errors at `loc`.
364 static llvm::Constant *
366  llvm::Type *llvmType,
367  const ModuleTranslation &moduleTranslation) {
368  if (!denseElementsAttr)
369  return nullptr;
370 
371  llvm::Type *innermostLLVMType = getInnermostElementType(llvmType);
372  if (!llvm::ConstantDataSequential::isElementTypeCompatible(innermostLLVMType))
373  return nullptr;
374 
375  ShapedType type = denseElementsAttr.getType();
376  if (type.getNumElements() == 0)
377  return nullptr;
378 
379  // Check that the raw data size matches what is expected for the scalar size.
380  // TODO: in theory, we could repack the data here to keep constructing from
381  // raw data.
382  // TODO: we may also need to consider endianness when cross-compiling to an
383  // architecture where it is different.
384  int64_t elementByteSize = denseElementsAttr.getRawData().size() /
385  denseElementsAttr.getNumElements();
386  if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits())
387  return nullptr;
388 
389  // Compute the shape of all dimensions but the innermost. Note that the
390  // innermost dimension may be that of the vector element type.
391  bool hasVectorElementType = isa<VectorType>(type.getElementType());
392  int64_t numAggregates =
393  denseElementsAttr.getNumElements() /
394  (hasVectorElementType ? 1
395  : denseElementsAttr.getType().getShape().back());
396  ArrayRef<int64_t> outerShape = type.getShape();
397  if (!hasVectorElementType)
398  outerShape = outerShape.drop_back();
399 
400  // Handle the case of vector splat, LLVM has special support for it.
401  if (denseElementsAttr.isSplat() &&
402  (isa<VectorType>(type) || hasVectorElementType)) {
403  llvm::Constant *splatValue = LLVM::detail::getLLVMConstant(
404  innermostLLVMType, denseElementsAttr.getSplatValue<Attribute>(), loc,
405  moduleTranslation);
406  llvm::Constant *splatVector =
407  llvm::ConstantDataVector::getSplat(0, splatValue);
408  SmallVector<llvm::Constant *> constants(numAggregates, splatVector);
409  ArrayRef<llvm::Constant *> constantsRef = constants;
410  return buildSequentialConstant(constantsRef, outerShape, llvmType, loc);
411  }
412  if (denseElementsAttr.isSplat())
413  return nullptr;
414 
415  // In case of non-splat, create a constructor for the innermost constant from
416  // a piece of raw data.
417  std::function<llvm::Constant *(StringRef)> buildCstData;
418  if (isa<TensorType>(type)) {
419  auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
420  if (vectorElementType && vectorElementType.getRank() == 1) {
421  buildCstData = [&](StringRef data) {
422  return llvm::ConstantDataVector::getRaw(
423  data, vectorElementType.getShape().back(), innermostLLVMType);
424  };
425  } else if (!vectorElementType) {
426  buildCstData = [&](StringRef data) {
427  return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
428  innermostLLVMType);
429  };
430  }
431  } else if (isa<VectorType>(type)) {
432  buildCstData = [&](StringRef data) {
433  return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
434  innermostLLVMType);
435  };
436  }
437  if (!buildCstData)
438  return nullptr;
439 
440  // Create innermost constants and defer to the default constant creation
441  // mechanism for other dimensions.
443  int64_t aggregateSize = denseElementsAttr.getType().getShape().back() *
444  (innermostLLVMType->getScalarSizeInBits() / 8);
445  constants.reserve(numAggregates);
446  for (unsigned i = 0; i < numAggregates; ++i) {
447  StringRef data(denseElementsAttr.getRawData().data() + i * aggregateSize,
448  aggregateSize);
449  constants.push_back(buildCstData(data));
450  }
451 
452  ArrayRef<llvm::Constant *> constantsRef = constants;
453  return buildSequentialConstant(constantsRef, outerShape, llvmType, loc);
454 }
455 
456 /// Convert a dense resource elements attribute to an LLVM IR constant using its
457 /// raw data storage if possible. This supports elements attributes of tensor or
458 /// vector type and avoids constructing separate objects for individual values
459 /// of the innermost dimension. Constants for other dimensions are still
460 /// constructed recursively. Returns nullptr on failure and emits errors at
461 /// `loc`.
462 static llvm::Constant *convertDenseResourceElementsAttr(
463  Location loc, DenseResourceElementsAttr denseResourceAttr,
464  llvm::Type *llvmType, const ModuleTranslation &moduleTranslation) {
465  assert(denseResourceAttr && "expected non-null attribute");
466 
467  llvm::Type *innermostLLVMType = getInnermostElementType(llvmType);
468  if (!llvm::ConstantDataSequential::isElementTypeCompatible(
469  innermostLLVMType)) {
470  emitError(loc, "no known conversion for innermost element type");
471  return nullptr;
472  }
473 
474  ShapedType type = denseResourceAttr.getType();
475  assert(type.getNumElements() > 0 && "Expected non-empty elements attribute");
476 
477  AsmResourceBlob *blob = denseResourceAttr.getRawHandle().getBlob();
478  if (!blob) {
479  emitError(loc, "resource does not exist");
480  return nullptr;
481  }
482 
483  ArrayRef<char> rawData = blob->getData();
484 
485  // Check that the raw data size matches what is expected for the scalar size.
486  // TODO: in theory, we could repack the data here to keep constructing from
487  // raw data.
488  // TODO: we may also need to consider endianness when cross-compiling to an
489  // architecture where it is different.
490  int64_t numElements = denseResourceAttr.getType().getNumElements();
491  int64_t elementByteSize = rawData.size() / numElements;
492  if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits()) {
493  emitError(loc, "raw data size does not match element type size");
494  return nullptr;
495  }
496 
497  // Compute the shape of all dimensions but the innermost. Note that the
498  // innermost dimension may be that of the vector element type.
499  bool hasVectorElementType = isa<VectorType>(type.getElementType());
500  int64_t numAggregates =
501  numElements / (hasVectorElementType
502  ? 1
503  : denseResourceAttr.getType().getShape().back());
504  ArrayRef<int64_t> outerShape = type.getShape();
505  if (!hasVectorElementType)
506  outerShape = outerShape.drop_back();
507 
508  // Create a constructor for the innermost constant from a piece of raw data.
509  std::function<llvm::Constant *(StringRef)> buildCstData;
510  if (isa<TensorType>(type)) {
511  auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
512  if (vectorElementType && vectorElementType.getRank() == 1) {
513  buildCstData = [&](StringRef data) {
514  return llvm::ConstantDataVector::getRaw(
515  data, vectorElementType.getShape().back(), innermostLLVMType);
516  };
517  } else if (!vectorElementType) {
518  buildCstData = [&](StringRef data) {
519  return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
520  innermostLLVMType);
521  };
522  }
523  } else if (isa<VectorType>(type)) {
524  buildCstData = [&](StringRef data) {
525  return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
526  innermostLLVMType);
527  };
528  }
529  if (!buildCstData) {
530  emitError(loc, "unsupported dense_resource type");
531  return nullptr;
532  }
533 
534  // Create innermost constants and defer to the default constant creation
535  // mechanism for other dimensions.
537  int64_t aggregateSize = denseResourceAttr.getType().getShape().back() *
538  (innermostLLVMType->getScalarSizeInBits() / 8);
539  constants.reserve(numAggregates);
540  for (unsigned i = 0; i < numAggregates; ++i) {
541  StringRef data(rawData.data() + i * aggregateSize, aggregateSize);
542  constants.push_back(buildCstData(data));
543  }
544 
545  ArrayRef<llvm::Constant *> constantsRef = constants;
546  return buildSequentialConstant(constantsRef, outerShape, llvmType, loc);
547 }
548 
549 /// Create an LLVM IR constant of `llvmType` from the MLIR attribute `attr`.
550 /// This currently supports integer, floating point, splat and dense element
551 /// attributes and combinations thereof. Also, an array attribute with two
552 /// elements is supported to represent a complex constant. In case of error,
553 /// report it to `loc` and return nullptr.
555  llvm::Type *llvmType, Attribute attr, Location loc,
556  const ModuleTranslation &moduleTranslation) {
557  if (!attr)
558  return llvm::UndefValue::get(llvmType);
559  if (auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
560  auto arrayAttr = dyn_cast<ArrayAttr>(attr);
561  if (!arrayAttr || arrayAttr.size() != 2) {
562  emitError(loc, "expected struct type to be a complex number");
563  return nullptr;
564  }
565  llvm::Type *elementType = structType->getElementType(0);
566  llvm::Constant *real =
567  getLLVMConstant(elementType, arrayAttr[0], loc, moduleTranslation);
568  if (!real)
569  return nullptr;
570  llvm::Constant *imag =
571  getLLVMConstant(elementType, arrayAttr[1], loc, moduleTranslation);
572  if (!imag)
573  return nullptr;
574  return llvm::ConstantStruct::get(structType, {real, imag});
575  }
576  // For integer types, we allow a mismatch in sizes as the index type in
577  // MLIR might have a different size than the index type in the LLVM module.
578  if (auto intAttr = dyn_cast<IntegerAttr>(attr))
579  return llvm::ConstantInt::get(
580  llvmType,
581  intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth()));
582  if (auto floatAttr = dyn_cast<FloatAttr>(attr)) {
583  const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
584  // Special case for 8-bit floats, which are represented by integers due to
585  // the lack of native fp8 types in LLVM at the moment. Additionally, handle
586  // targets (like AMDGPU) that don't implement bfloat and convert all bfloats
587  // to i16.
588  unsigned floatWidth = APFloat::getSizeInBits(sem);
589  if (llvmType->isIntegerTy(floatWidth))
590  return llvm::ConstantInt::get(llvmType,
591  floatAttr.getValue().bitcastToAPInt());
592  if (llvmType !=
593  llvm::Type::getFloatingPointTy(llvmType->getContext(),
594  floatAttr.getValue().getSemantics())) {
595  emitError(loc, "FloatAttr does not match expected type of the constant");
596  return nullptr;
597  }
598  return llvm::ConstantFP::get(llvmType, floatAttr.getValue());
599  }
600  if (auto funcAttr = dyn_cast<FlatSymbolRefAttr>(attr))
601  return llvm::ConstantExpr::getBitCast(
602  moduleTranslation.lookupFunction(funcAttr.getValue()), llvmType);
603  if (auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
604  llvm::Type *elementType;
605  uint64_t numElements;
606  bool isScalable = false;
607  if (auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
608  elementType = arrayTy->getElementType();
609  numElements = arrayTy->getNumElements();
610  } else if (auto *fVectorTy = dyn_cast<llvm::FixedVectorType>(llvmType)) {
611  elementType = fVectorTy->getElementType();
612  numElements = fVectorTy->getNumElements();
613  } else if (auto *sVectorTy = dyn_cast<llvm::ScalableVectorType>(llvmType)) {
614  elementType = sVectorTy->getElementType();
615  numElements = sVectorTy->getMinNumElements();
616  isScalable = true;
617  } else {
618  llvm_unreachable("unrecognized constant vector type");
619  }
620  // Splat value is a scalar. Extract it only if the element type is not
621  // another sequence type. The recursion terminates because each step removes
622  // one outer sequential type.
623  bool elementTypeSequential =
624  isa<llvm::ArrayType, llvm::VectorType>(elementType);
625  llvm::Constant *child = getLLVMConstant(
626  elementType,
627  elementTypeSequential ? splatAttr
628  : splatAttr.getSplatValue<Attribute>(),
629  loc, moduleTranslation);
630  if (!child)
631  return nullptr;
632  if (llvmType->isVectorTy())
633  return llvm::ConstantVector::getSplat(
634  llvm::ElementCount::get(numElements, /*Scalable=*/isScalable), child);
635  if (llvmType->isArrayTy()) {
636  auto *arrayType = llvm::ArrayType::get(elementType, numElements);
637  if (child->isZeroValue()) {
638  return llvm::ConstantAggregateZero::get(arrayType);
639  } else {
640  if (llvm::ConstantDataSequential::isElementTypeCompatible(
641  elementType)) {
642  // TODO: Handle all compatible types. This code only handles integer.
643  if (llvm::IntegerType *iTy =
644  dyn_cast<llvm::IntegerType>(elementType)) {
645  if (llvm::ConstantInt *ci = dyn_cast<llvm::ConstantInt>(child)) {
646  if (ci->getBitWidth() == 8) {
647  SmallVector<int8_t> constants(numElements, ci->getZExtValue());
648  return llvm::ConstantDataArray::get(elementType->getContext(),
649  constants);
650  }
651  if (ci->getBitWidth() == 16) {
652  SmallVector<int16_t> constants(numElements, ci->getZExtValue());
653  return llvm::ConstantDataArray::get(elementType->getContext(),
654  constants);
655  }
656  if (ci->getBitWidth() == 32) {
657  SmallVector<int32_t> constants(numElements, ci->getZExtValue());
658  return llvm::ConstantDataArray::get(elementType->getContext(),
659  constants);
660  }
661  if (ci->getBitWidth() == 64) {
662  SmallVector<int64_t> constants(numElements, ci->getZExtValue());
663  return llvm::ConstantDataArray::get(elementType->getContext(),
664  constants);
665  }
666  }
667  }
668  }
669  // std::vector is used here to accomodate large number of elements that
670  // exceed SmallVector capacity.
671  std::vector<llvm::Constant *> constants(numElements, child);
672  return llvm::ConstantArray::get(arrayType, constants);
673  }
674  }
675  }
676 
677  // Try using raw elements data if possible.
678  if (llvm::Constant *result =
679  convertDenseElementsAttr(loc, dyn_cast<DenseElementsAttr>(attr),
680  llvmType, moduleTranslation)) {
681  return result;
682  }
683 
684  if (auto denseResourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
685  return convertDenseResourceElementsAttr(loc, denseResourceAttr, llvmType,
686  moduleTranslation);
687  }
688 
689  // Fall back to element-by-element construction otherwise.
690  if (auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
691  assert(elementsAttr.getShapedType().hasStaticShape());
692  assert(!elementsAttr.getShapedType().getShape().empty() &&
693  "unexpected empty elements attribute shape");
694 
696  constants.reserve(elementsAttr.getNumElements());
697  llvm::Type *innermostType = getInnermostElementType(llvmType);
698  for (auto n : elementsAttr.getValues<Attribute>()) {
699  constants.push_back(
700  getLLVMConstant(innermostType, n, loc, moduleTranslation));
701  if (!constants.back())
702  return nullptr;
703  }
704  ArrayRef<llvm::Constant *> constantsRef = constants;
705  llvm::Constant *result = buildSequentialConstant(
706  constantsRef, elementsAttr.getShapedType().getShape(), llvmType, loc);
707  assert(constantsRef.empty() && "did not consume all elemental constants");
708  return result;
709  }
710 
711  if (auto stringAttr = dyn_cast<StringAttr>(attr)) {
713  moduleTranslation.getLLVMContext(),
714  ArrayRef<char>{stringAttr.getValue().data(),
715  stringAttr.getValue().size()});
716  }
717  emitError(loc, "unsupported constant value");
718  return nullptr;
719 }
720 
721 ModuleTranslation::ModuleTranslation(Operation *module,
722  std::unique_ptr<llvm::Module> llvmModule)
723  : mlirModule(module), llvmModule(std::move(llvmModule)),
724  debugTranslation(
725  std::make_unique<DebugTranslation>(module, *this->llvmModule)),
726  loopAnnotationTranslation(std::make_unique<LoopAnnotationTranslation>(
727  *this, *this->llvmModule)),
728  typeTranslator(this->llvmModule->getContext()),
729  iface(module->getContext()) {
730  assert(satisfiesLLVMModule(mlirModule) &&
731  "mlirModule should honor LLVM's module semantics.");
732 }
733 
734 ModuleTranslation::~ModuleTranslation() {
735  if (ompBuilder)
736  ompBuilder->finalize();
737 }
738 
740  SmallVector<Region *> toProcess;
741  toProcess.push_back(&region);
742  while (!toProcess.empty()) {
743  Region *current = toProcess.pop_back_val();
744  for (Block &block : *current) {
745  blockMapping.erase(&block);
746  for (Value arg : block.getArguments())
747  valueMapping.erase(arg);
748  for (Operation &op : block) {
749  for (Value value : op.getResults())
750  valueMapping.erase(value);
751  if (op.hasSuccessors())
752  branchMapping.erase(&op);
753  if (isa<LLVM::GlobalOp>(op))
754  globalsMapping.erase(&op);
755  if (isa<LLVM::CallOp>(op))
756  callMapping.erase(&op);
757  llvm::append_range(
758  toProcess,
759  llvm::map_range(op.getRegions(), [](Region &r) { return &r; }));
760  }
761  }
762  }
763 }
764 
765 /// Get the SSA value passed to the current block from the terminator operation
766 /// of its predecessor.
767 static Value getPHISourceValue(Block *current, Block *pred,
768  unsigned numArguments, unsigned index) {
769  Operation &terminator = *pred->getTerminator();
770  if (isa<LLVM::BrOp>(terminator))
771  return terminator.getOperand(index);
772 
773 #ifndef NDEBUG
774  llvm::SmallPtrSet<Block *, 4> seenSuccessors;
775  for (unsigned i = 0, e = terminator.getNumSuccessors(); i < e; ++i) {
776  Block *successor = terminator.getSuccessor(i);
777  auto branch = cast<BranchOpInterface>(terminator);
778  SuccessorOperands successorOperands = branch.getSuccessorOperands(i);
779  assert(
780  (!seenSuccessors.contains(successor) || successorOperands.empty()) &&
781  "successors with arguments in LLVM branches must be different blocks");
782  seenSuccessors.insert(successor);
783  }
784 #endif
785 
786  // For instructions that branch based on a condition value, we need to take
787  // the operands for the branch that was taken.
788  if (auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
789  // For conditional branches, we take the operands from either the "true" or
790  // the "false" branch.
791  return condBranchOp.getSuccessor(0) == current
792  ? condBranchOp.getTrueDestOperands()[index]
793  : condBranchOp.getFalseDestOperands()[index];
794  }
795 
796  if (auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
797  // For switches, we take the operands from either the default case, or from
798  // the case branch that was taken.
799  if (switchOp.getDefaultDestination() == current)
800  return switchOp.getDefaultOperands()[index];
801  for (const auto &i : llvm::enumerate(switchOp.getCaseDestinations()))
802  if (i.value() == current)
803  return switchOp.getCaseOperands(i.index())[index];
804  }
805 
806  if (auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
807  return invokeOp.getNormalDest() == current
808  ? invokeOp.getNormalDestOperands()[index]
809  : invokeOp.getUnwindDestOperands()[index];
810  }
811 
812  llvm_unreachable(
813  "only branch, switch or invoke operations can be terminators "
814  "of a block that has successors");
815 }
816 
817 /// Connect the PHI nodes to the results of preceding blocks.
819  const ModuleTranslation &state) {
820  // Skip the first block, it cannot be branched to and its arguments correspond
821  // to the arguments of the LLVM function.
822  for (Block &bb : llvm::drop_begin(region)) {
823  llvm::BasicBlock *llvmBB = state.lookupBlock(&bb);
824  auto phis = llvmBB->phis();
825  auto numArguments = bb.getNumArguments();
826  assert(numArguments == std::distance(phis.begin(), phis.end()));
827  for (auto [index, phiNode] : llvm::enumerate(phis)) {
828  for (auto *pred : bb.getPredecessors()) {
829  // Find the LLVM IR block that contains the converted terminator
830  // instruction and use it in the PHI node. Note that this block is not
831  // necessarily the same as state.lookupBlock(pred), some operations
832  // (in particular, OpenMP operations using OpenMPIRBuilder) may have
833  // split the blocks.
834  llvm::Instruction *terminator =
835  state.lookupBranch(pred->getTerminator());
836  assert(terminator && "missing the mapping for a terminator");
837  phiNode.addIncoming(state.lookupValue(getPHISourceValue(
838  &bb, pred, numArguments, index)),
839  terminator->getParent());
840  }
841  }
842  }
843 }
844 
846  llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic,
848  llvm::Module *module = builder.GetInsertBlock()->getModule();
849  llvm::Function *fn = llvm::Intrinsic::getDeclaration(module, intrinsic, tys);
850  return builder.CreateCall(fn, args);
851 }
852 
854  llvm::IRBuilderBase &builder, ModuleTranslation &moduleTranslation,
855  Operation *intrOp, llvm::Intrinsic::ID intrinsic, unsigned numResults,
856  ArrayRef<unsigned> overloadedResults, ArrayRef<unsigned> overloadedOperands,
857  ArrayRef<unsigned> immArgPositions,
858  ArrayRef<StringLiteral> immArgAttrNames) {
859  assert(immArgPositions.size() == immArgAttrNames.size() &&
860  "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
861  "length");
862 
863  // Map operands and attributes to LLVM values.
864  auto operands = moduleTranslation.lookupValues(intrOp->getOperands());
865  SmallVector<llvm::Value *> args(immArgPositions.size() + operands.size());
866  for (auto [immArgPos, immArgName] :
867  llvm::zip(immArgPositions, immArgAttrNames)) {
868  auto attr = llvm::cast<TypedAttr>(intrOp->getAttr(immArgName));
869  assert(attr.getType().isIntOrFloat() && "expected int or float immarg");
870  auto *type = moduleTranslation.convertType(attr.getType());
871  args[immArgPos] = LLVM::detail::getLLVMConstant(
872  type, attr, intrOp->getLoc(), moduleTranslation);
873  }
874  unsigned opArg = 0;
875  for (auto &arg : args) {
876  if (!arg)
877  arg = operands[opArg++];
878  }
879 
880  // Resolve overloaded intrinsic declaration.
881  SmallVector<llvm::Type *> overloadedTypes;
882  for (unsigned overloadedResultIdx : overloadedResults) {
883  if (numResults > 1) {
884  // More than one result is mapped to an LLVM struct.
885  overloadedTypes.push_back(moduleTranslation.convertType(
886  llvm::cast<LLVM::LLVMStructType>(intrOp->getResult(0).getType())
887  .getBody()[overloadedResultIdx]));
888  } else {
889  overloadedTypes.push_back(
890  moduleTranslation.convertType(intrOp->getResult(0).getType()));
891  }
892  }
893  for (unsigned overloadedOperandIdx : overloadedOperands)
894  overloadedTypes.push_back(args[overloadedOperandIdx]->getType());
895  llvm::Module *module = builder.GetInsertBlock()->getModule();
896  llvm::Function *llvmIntr =
897  llvm::Intrinsic::getDeclaration(module, intrinsic, overloadedTypes);
898 
899  return builder.CreateCall(llvmIntr, args);
900 }
901 
902 /// Given a single MLIR operation, create the corresponding LLVM IR operation
903 /// using the `builder`.
904 LogicalResult ModuleTranslation::convertOperation(Operation &op,
905  llvm::IRBuilderBase &builder,
906  bool recordInsertions) {
907  const LLVMTranslationDialectInterface *opIface = iface.getInterfaceFor(&op);
908  if (!opIface)
909  return op.emitError("cannot be converted to LLVM IR: missing "
910  "`LLVMTranslationDialectInterface` registration for "
911  "dialect for op: ")
912  << op.getName();
913 
914  InstructionCapturingInserter::CollectionScope scope(builder,
915  recordInsertions);
916  if (failed(opIface->convertOperation(&op, builder, *this)))
917  return op.emitError("LLVM Translation failed for operation: ")
918  << op.getName();
919 
920  return convertDialectAttributes(&op, scope.getCapturedInstructions());
921 }
922 
923 /// Convert block to LLVM IR. Unless `ignoreArguments` is set, emit PHI nodes
924 /// to define values corresponding to the MLIR block arguments. These nodes
925 /// are not connected to the source basic blocks, which may not exist yet. Uses
926 /// `builder` to construct the LLVM IR. Expects the LLVM IR basic block to have
927 /// been created for `bb` and included in the block mapping. Inserts new
928 /// instructions at the end of the block and leaves `builder` in a state
929 /// suitable for further insertion into the end of the block.
930 LogicalResult ModuleTranslation::convertBlockImpl(Block &bb,
931  bool ignoreArguments,
932  llvm::IRBuilderBase &builder,
933  bool recordInsertions) {
934  builder.SetInsertPoint(lookupBlock(&bb));
935  auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
936 
937  // Before traversing operations, make block arguments available through
938  // value remapping and PHI nodes, but do not add incoming edges for the PHI
939  // nodes just yet: those values may be defined by this or following blocks.
940  // This step is omitted if "ignoreArguments" is set. The arguments of the
941  // first block have been already made available through the remapping of
942  // LLVM function arguments.
943  if (!ignoreArguments) {
944  auto predecessors = bb.getPredecessors();
945  unsigned numPredecessors =
946  std::distance(predecessors.begin(), predecessors.end());
947  for (auto arg : bb.getArguments()) {
948  auto wrappedType = arg.getType();
949  if (!isCompatibleType(wrappedType))
950  return emitError(bb.front().getLoc(),
951  "block argument does not have an LLVM type");
952  llvm::Type *type = convertType(wrappedType);
953  llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
954  mapValue(arg, phi);
955  }
956  }
957 
958  // Traverse operations.
959  for (auto &op : bb) {
960  // Set the current debug location within the builder.
961  builder.SetCurrentDebugLocation(
962  debugTranslation->translateLoc(op.getLoc(), subprogram));
963 
964  if (failed(convertOperation(op, builder, recordInsertions)))
965  return failure();
966 
967  // Set the branch weight metadata on the translated instruction.
968  if (auto iface = dyn_cast<BranchWeightOpInterface>(op))
970  }
971 
972  return success();
973 }
974 
975 /// A helper method to get the single Block in an operation honoring LLVM's
976 /// module requirements.
977 static Block &getModuleBody(Operation *module) {
978  return module->getRegion(0).front();
979 }
980 
981 /// A helper method to decide if a constant must not be set as a global variable
982 /// initializer. For an external linkage variable, the variable with an
983 /// initializer is considered externally visible and defined in this module, the
984 /// variable without an initializer is externally available and is defined
985 /// elsewhere.
986 static bool shouldDropGlobalInitializer(llvm::GlobalValue::LinkageTypes linkage,
987  llvm::Constant *cst) {
988  return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
989  linkage == llvm::GlobalVariable::ExternalWeakLinkage;
990 }
991 
992 /// Sets the runtime preemption specifier of `gv` to dso_local if
993 /// `dsoLocalRequested` is true, otherwise it is left unchanged.
994 static void addRuntimePreemptionSpecifier(bool dsoLocalRequested,
995  llvm::GlobalValue *gv) {
996  if (dsoLocalRequested)
997  gv->setDSOLocal(true);
998 }
999 
1000 /// Create named global variables that correspond to llvm.mlir.global
1001 /// definitions. Convert llvm.global_ctors and global_dtors ops.
1002 LogicalResult ModuleTranslation::convertGlobals() {
1003  // Mapping from compile unit to its respective set of global variables.
1005 
1006  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1007  llvm::Type *type = convertType(op.getType());
1008  llvm::Constant *cst = nullptr;
1009  if (op.getValueOrNull()) {
1010  // String attributes are treated separately because they cannot appear as
1011  // in-function constants and are thus not supported by getLLVMConstant.
1012  if (auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1013  cst = llvm::ConstantDataArray::getString(
1014  llvmModule->getContext(), strAttr.getValue(), /*AddNull=*/false);
1015  type = cst->getType();
1016  } else if (!(cst = getLLVMConstant(type, op.getValueOrNull(), op.getLoc(),
1017  *this))) {
1018  return failure();
1019  }
1020  }
1021 
1022  auto linkage = convertLinkageToLLVM(op.getLinkage());
1023  auto addrSpace = op.getAddrSpace();
1024 
1025  // LLVM IR requires constant with linkage other than external or weak
1026  // external to have initializers. If MLIR does not provide an initializer,
1027  // default to undef.
1028  bool dropInitializer = shouldDropGlobalInitializer(linkage, cst);
1029  if (!dropInitializer && !cst)
1030  cst = llvm::UndefValue::get(type);
1031  else if (dropInitializer && cst)
1032  cst = nullptr;
1033 
1034  auto *var = new llvm::GlobalVariable(
1035  *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1036  /*InsertBefore=*/nullptr,
1037  op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1038  : llvm::GlobalValue::NotThreadLocal,
1039  addrSpace);
1040 
1041  if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1042  auto selectorOp = cast<ComdatSelectorOp>(
1044  var->setComdat(comdatMapping.lookup(selectorOp));
1045  }
1046 
1047  if (op.getUnnamedAddr().has_value())
1048  var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1049 
1050  if (op.getSection().has_value())
1051  var->setSection(*op.getSection());
1052 
1053  addRuntimePreemptionSpecifier(op.getDsoLocal(), var);
1054 
1055  std::optional<uint64_t> alignment = op.getAlignment();
1056  if (alignment.has_value())
1057  var->setAlignment(llvm::MaybeAlign(alignment.value()));
1058 
1059  var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1060 
1061  globalsMapping.try_emplace(op, var);
1062 
1063  // Add debug information if present.
1064  if (op.getDbgExpr()) {
1065  llvm::DIGlobalVariableExpression *diGlobalExpr =
1066  debugTranslation->translateGlobalVariableExpression(op.getDbgExpr());
1067  llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1068  var->addDebugInfo(diGlobalExpr);
1069 
1070  // There is no `globals` field in DICompileUnitAttr which can be directly
1071  // assigned to DICompileUnit. We have to build the list by looking at the
1072  // dbgExpr of all the GlobalOps. The scope of the variable is used to get
1073  // the DICompileUnit in which to add it. But for the languages that
1074  // support modules, the scope hierarchy can be
1075  // variable -> module -> compile unit
1076  // If a variable scope points to the module then we use the scope of the
1077  // module to get the compile unit.
1078  llvm::DIScope *scope = diGlobalVar->getScope();
1079  if (llvm::DIModule *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1080  scope = mod->getScope();
1081 
1082  // Get the compile unit (scope) of the the global variable.
1083  if (llvm::DICompileUnit *compileUnit =
1084  dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1085  // Update the compile unit with this incoming global variable expression
1086  // during the finalizing step later.
1087  allGVars[compileUnit].push_back(diGlobalExpr);
1088  }
1089  }
1090  }
1091 
1092  // Convert global variable bodies. This is done after all global variables
1093  // have been created in LLVM IR because a global body may refer to another
1094  // global or itself. So all global variables need to be mapped first.
1095  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1096  if (Block *initializer = op.getInitializerBlock()) {
1097  llvm::IRBuilder<> builder(llvmModule->getContext());
1098 
1099  [[maybe_unused]] int numConstantsHit = 0;
1100  [[maybe_unused]] int numConstantsErased = 0;
1101  DenseMap<llvm::ConstantAggregate *, int> constantAggregateUseMap;
1102 
1103  for (auto &op : initializer->without_terminator()) {
1104  if (failed(convertOperation(op, builder)))
1105  return emitError(op.getLoc(), "fail to convert global initializer");
1106  auto *cst = dyn_cast<llvm::Constant>(lookupValue(op.getResult(0)));
1107  if (!cst)
1108  return emitError(op.getLoc(), "unemittable constant value");
1109 
1110  // When emitting an LLVM constant, a new constant is created and the old
1111  // constant may become dangling and take space. We should remove the
1112  // dangling constants to avoid memory explosion especially for constant
1113  // arrays whose number of elements is large.
1114  // Because multiple operations may refer to the same constant, we need
1115  // to count the number of uses of each constant array and remove it only
1116  // when the count becomes zero.
1117  if (auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1118  numConstantsHit++;
1119  Value result = op.getResult(0);
1120  int numUsers = std::distance(result.use_begin(), result.use_end());
1121  auto [iterator, inserted] =
1122  constantAggregateUseMap.try_emplace(agg, numUsers);
1123  if (!inserted) {
1124  // Key already exists, update the value
1125  iterator->second += numUsers;
1126  }
1127  }
1128  // Scan the operands of the operation to decrement the use count of
1129  // constants. Erase the constant if the use count becomes zero.
1130  for (Value v : op.getOperands()) {
1131  auto cst = dyn_cast<llvm::ConstantAggregate>(lookupValue(v));
1132  if (!cst)
1133  continue;
1134  auto iter = constantAggregateUseMap.find(cst);
1135  assert(iter != constantAggregateUseMap.end() && "constant not found");
1136  iter->second--;
1137  if (iter->second == 0) {
1138  // NOTE: cannot call removeDeadConstantUsers() here because it
1139  // may remove the constant which has uses not be converted yet.
1140  if (cst->user_empty()) {
1141  cst->destroyConstant();
1142  numConstantsErased++;
1143  }
1144  constantAggregateUseMap.erase(iter);
1145  }
1146  }
1147  }
1148 
1149  ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1150  llvm::Constant *cst =
1151  cast<llvm::Constant>(lookupValue(ret.getOperand(0)));
1152  auto *global = cast<llvm::GlobalVariable>(lookupGlobal(op));
1153  if (!shouldDropGlobalInitializer(global->getLinkage(), cst))
1154  global->setInitializer(cst);
1155 
1156  // Try to remove the dangling constants again after all operations are
1157  // converted.
1158  for (auto it : constantAggregateUseMap) {
1159  auto cst = it.first;
1160  cst->removeDeadConstantUsers();
1161  if (cst->user_empty()) {
1162  cst->destroyConstant();
1163  numConstantsErased++;
1164  }
1165  }
1166 
1167  LLVM_DEBUG(llvm::dbgs()
1168  << "Convert initializer for " << op.getName() << "\n";
1169  llvm::dbgs() << numConstantsHit << " new constants hit\n";
1170  llvm::dbgs()
1171  << numConstantsErased << " dangling constants erased\n";);
1172  }
1173  }
1174 
1175  // Convert llvm.mlir.global_ctors and dtors.
1176  for (Operation &op : getModuleBody(mlirModule)) {
1177  auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1178  auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1179  if (!ctorOp && !dtorOp)
1180  continue;
1181  auto range = ctorOp ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1182  : llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1183  auto appendGlobalFn =
1184  ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1185  for (auto symbolAndPriority : range) {
1186  llvm::Function *f = lookupFunction(
1187  cast<FlatSymbolRefAttr>(std::get<0>(symbolAndPriority)).getValue());
1188  appendGlobalFn(*llvmModule, f,
1189  cast<IntegerAttr>(std::get<1>(symbolAndPriority)).getInt(),
1190  /*Data=*/nullptr);
1191  }
1192  }
1193 
1194  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1195  if (failed(convertDialectAttributes(op, {})))
1196  return failure();
1197 
1198  // Finally, update the compile units their respective sets of global variables
1199  // created earlier.
1200  for (const auto &[compileUnit, globals] : allGVars) {
1201  compileUnit->replaceGlobalVariables(
1202  llvm::MDTuple::get(getLLVMContext(), globals));
1203  }
1204 
1205  return success();
1206 }
1207 
1208 /// Attempts to add an attribute identified by `key`, optionally with the given
1209 /// `value` to LLVM function `llvmFunc`. Reports errors at `loc` if any. If the
1210 /// attribute has a kind known to LLVM IR, create the attribute of this kind,
1211 /// otherwise keep it as a string attribute. Performs additional checks for
1212 /// attributes known to have or not have a value in order to avoid assertions
1213 /// inside LLVM upon construction.
1215  llvm::Function *llvmFunc,
1216  StringRef key,
1217  StringRef value = StringRef()) {
1218  auto kind = llvm::Attribute::getAttrKindFromName(key);
1219  if (kind == llvm::Attribute::None) {
1220  llvmFunc->addFnAttr(key, value);
1221  return success();
1222  }
1223 
1224  if (llvm::Attribute::isIntAttrKind(kind)) {
1225  if (value.empty())
1226  return emitError(loc) << "LLVM attribute '" << key << "' expects a value";
1227 
1228  int64_t result;
1229  if (!value.getAsInteger(/*Radix=*/0, result))
1230  llvmFunc->addFnAttr(
1231  llvm::Attribute::get(llvmFunc->getContext(), kind, result));
1232  else
1233  llvmFunc->addFnAttr(key, value);
1234  return success();
1235  }
1236 
1237  if (!value.empty())
1238  return emitError(loc) << "LLVM attribute '" << key
1239  << "' does not expect a value, found '" << value
1240  << "'";
1241 
1242  llvmFunc->addFnAttr(kind);
1243  return success();
1244 }
1245 
1246 /// Attaches the attributes listed in the given array attribute to `llvmFunc`.
1247 /// Reports error to `loc` if any and returns immediately. Expects `attributes`
1248 /// to be an array attribute containing either string attributes, treated as
1249 /// value-less LLVM attributes, or array attributes containing two string
1250 /// attributes, with the first string being the name of the corresponding LLVM
1251 /// attribute and the second string beings its value. Note that even integer
1252 /// attributes are expected to have their values expressed as strings.
1253 static LogicalResult
1254 forwardPassthroughAttributes(Location loc, std::optional<ArrayAttr> attributes,
1255  llvm::Function *llvmFunc) {
1256  if (!attributes)
1257  return success();
1258 
1259  for (Attribute attr : *attributes) {
1260  if (auto stringAttr = dyn_cast<StringAttr>(attr)) {
1261  if (failed(
1262  checkedAddLLVMFnAttribute(loc, llvmFunc, stringAttr.getValue())))
1263  return failure();
1264  continue;
1265  }
1266 
1267  auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1268  if (!arrayAttr || arrayAttr.size() != 2)
1269  return emitError(loc)
1270  << "expected 'passthrough' to contain string or array attributes";
1271 
1272  auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1273  auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1274  if (!keyAttr || !valueAttr)
1275  return emitError(loc)
1276  << "expected arrays within 'passthrough' to contain two strings";
1277 
1278  if (failed(checkedAddLLVMFnAttribute(loc, llvmFunc, keyAttr.getValue(),
1279  valueAttr.getValue())))
1280  return failure();
1281  }
1282  return success();
1283 }
1284 
1285 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1286  // Clear the block, branch value mappings, they are only relevant within one
1287  // function.
1288  blockMapping.clear();
1289  valueMapping.clear();
1290  branchMapping.clear();
1291  llvm::Function *llvmFunc = lookupFunction(func.getName());
1292 
1293  // Add function arguments to the value remapping table.
1294  for (auto [mlirArg, llvmArg] :
1295  llvm::zip(func.getArguments(), llvmFunc->args()))
1296  mapValue(mlirArg, &llvmArg);
1297 
1298  // Check the personality and set it.
1299  if (func.getPersonality()) {
1300  llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1301  if (llvm::Constant *pfunc = getLLVMConstant(ty, func.getPersonalityAttr(),
1302  func.getLoc(), *this))
1303  llvmFunc->setPersonalityFn(pfunc);
1304  }
1305 
1306  if (std::optional<StringRef> section = func.getSection())
1307  llvmFunc->setSection(*section);
1308 
1309  if (func.getArmStreaming())
1310  llvmFunc->addFnAttr("aarch64_pstate_sm_enabled");
1311  else if (func.getArmLocallyStreaming())
1312  llvmFunc->addFnAttr("aarch64_pstate_sm_body");
1313  else if (func.getArmStreamingCompatible())
1314  llvmFunc->addFnAttr("aarch64_pstate_sm_compatible");
1315 
1316  if (func.getArmNewZa())
1317  llvmFunc->addFnAttr("aarch64_new_za");
1318  else if (func.getArmInZa())
1319  llvmFunc->addFnAttr("aarch64_in_za");
1320  else if (func.getArmOutZa())
1321  llvmFunc->addFnAttr("aarch64_out_za");
1322  else if (func.getArmInoutZa())
1323  llvmFunc->addFnAttr("aarch64_inout_za");
1324  else if (func.getArmPreservesZa())
1325  llvmFunc->addFnAttr("aarch64_preserves_za");
1326 
1327  if (auto targetCpu = func.getTargetCpu())
1328  llvmFunc->addFnAttr("target-cpu", *targetCpu);
1329 
1330  if (auto targetFeatures = func.getTargetFeatures())
1331  llvmFunc->addFnAttr("target-features", targetFeatures->getFeaturesString());
1332 
1333  if (auto attr = func.getVscaleRange())
1334  llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1335  getLLVMContext(), attr->getMinRange().getInt(),
1336  attr->getMaxRange().getInt()));
1337 
1338  if (auto unsafeFpMath = func.getUnsafeFpMath())
1339  llvmFunc->addFnAttr("unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1340 
1341  if (auto noInfsFpMath = func.getNoInfsFpMath())
1342  llvmFunc->addFnAttr("no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1343 
1344  if (auto noNansFpMath = func.getNoNansFpMath())
1345  llvmFunc->addFnAttr("no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1346 
1347  if (auto approxFuncFpMath = func.getApproxFuncFpMath())
1348  llvmFunc->addFnAttr("approx-func-fp-math",
1349  llvm::toStringRef(*approxFuncFpMath));
1350 
1351  if (auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1352  llvmFunc->addFnAttr("no-signed-zeros-fp-math",
1353  llvm::toStringRef(*noSignedZerosFpMath));
1354 
1355  // Add function attribute frame-pointer, if found.
1356  if (FramePointerKindAttr attr = func.getFramePointerAttr())
1357  llvmFunc->addFnAttr("frame-pointer",
1358  LLVM::framePointerKind::stringifyFramePointerKind(
1359  (attr.getFramePointerKind())));
1360 
1361  // First, create all blocks so we can jump to them.
1362  llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1363  for (auto &bb : func) {
1364  auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1365  llvmBB->insertInto(llvmFunc);
1366  mapBlock(&bb, llvmBB);
1367  }
1368 
1369  // Then, convert blocks one by one in topological order to ensure defs are
1370  // converted before uses.
1371  auto blocks = getBlocksSortedByDominance(func.getBody());
1372  for (Block *bb : blocks) {
1373  CapturingIRBuilder builder(llvmContext);
1374  if (failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1375  /*recordInsertions=*/true)))
1376  return failure();
1377  }
1378 
1379  // After all blocks have been traversed and values mapped, connect the PHI
1380  // nodes to the results of preceding blocks.
1381  detail::connectPHINodes(func.getBody(), *this);
1382 
1383  // Finally, convert dialect attributes attached to the function.
1384  return convertDialectAttributes(func, {});
1385 }
1386 
1387 LogicalResult ModuleTranslation::convertDialectAttributes(
1388  Operation *op, ArrayRef<llvm::Instruction *> instructions) {
1389  for (NamedAttribute attribute : op->getDialectAttrs())
1390  if (failed(iface.amendOperation(op, instructions, attribute, *this)))
1391  return failure();
1392  return success();
1393 }
1394 
1395 /// Converts memory effect attributes from `func` and attaches them to
1396 /// `llvmFunc`.
1397 static void convertFunctionMemoryAttributes(LLVMFuncOp func,
1398  llvm::Function *llvmFunc) {
1399  if (!func.getMemory())
1400  return;
1401 
1402  MemoryEffectsAttr memEffects = func.getMemoryAttr();
1403 
1404  // Add memory effects incrementally.
1405  llvm::MemoryEffects newMemEffects =
1406  llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1407  convertModRefInfoToLLVM(memEffects.getArgMem()));
1408  newMemEffects |= llvm::MemoryEffects(
1409  llvm::MemoryEffects::Location::InaccessibleMem,
1410  convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1411  newMemEffects |=
1412  llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1413  convertModRefInfoToLLVM(memEffects.getOther()));
1414  llvmFunc->setMemoryEffects(newMemEffects);
1415 }
1416 
1417 /// Converts function attributes from `func` and attaches them to `llvmFunc`.
1418 static void convertFunctionAttributes(LLVMFuncOp func,
1419  llvm::Function *llvmFunc) {
1420  if (func.getNoInlineAttr())
1421  llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1422  if (func.getAlwaysInlineAttr())
1423  llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1424  if (func.getOptimizeNoneAttr())
1425  llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1426  convertFunctionMemoryAttributes(func, llvmFunc);
1427 }
1428 
1430 ModuleTranslation::convertParameterAttrs(LLVMFuncOp func, int argIdx,
1431  DictionaryAttr paramAttrs) {
1432  llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1433  auto attrNameToKindMapping = getAttrNameToKindMapping();
1434 
1435  for (auto namedAttr : paramAttrs) {
1436  auto it = attrNameToKindMapping.find(namedAttr.getName());
1437  if (it != attrNameToKindMapping.end()) {
1438  llvm::Attribute::AttrKind llvmKind = it->second;
1439 
1440  llvm::TypeSwitch<Attribute>(namedAttr.getValue())
1441  .Case<TypeAttr>([&](auto typeAttr) {
1442  attrBuilder.addTypeAttr(llvmKind, convertType(typeAttr.getValue()));
1443  })
1444  .Case<IntegerAttr>([&](auto intAttr) {
1445  attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1446  })
1447  .Case<UnitAttr>([&](auto) { attrBuilder.addAttribute(llvmKind); });
1448  } else if (namedAttr.getNameDialect()) {
1449  if (failed(iface.convertParameterAttr(func, argIdx, namedAttr, *this)))
1450  return failure();
1451  }
1452  }
1453 
1454  return attrBuilder;
1455 }
1456 
1457 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1458  // Declare all functions first because there may be function calls that form a
1459  // call graph with cycles, or global initializers that reference functions.
1460  for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1461  llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1462  function.getName(),
1463  cast<llvm::FunctionType>(convertType(function.getFunctionType())));
1464  llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1465  llvmFunc->setLinkage(convertLinkageToLLVM(function.getLinkage()));
1466  llvmFunc->setCallingConv(convertCConvToLLVM(function.getCConv()));
1467  mapFunction(function.getName(), llvmFunc);
1468  addRuntimePreemptionSpecifier(function.getDsoLocal(), llvmFunc);
1469 
1470  // Convert function attributes.
1471  convertFunctionAttributes(function, llvmFunc);
1472 
1473  // Convert function_entry_count attribute to metadata.
1474  if (std::optional<uint64_t> entryCount = function.getFunctionEntryCount())
1475  llvmFunc->setEntryCount(entryCount.value());
1476 
1477  // Convert result attributes.
1478  if (ArrayAttr allResultAttrs = function.getAllResultAttrs()) {
1479  DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1480  FailureOr<llvm::AttrBuilder> attrBuilder =
1481  convertParameterAttrs(function, -1, resultAttrs);
1482  if (failed(attrBuilder))
1483  return failure();
1484  llvmFunc->addRetAttrs(*attrBuilder);
1485  }
1486 
1487  // Convert argument attributes.
1488  for (auto [argIdx, llvmArg] : llvm::enumerate(llvmFunc->args())) {
1489  if (DictionaryAttr argAttrs = function.getArgAttrDict(argIdx)) {
1490  FailureOr<llvm::AttrBuilder> attrBuilder =
1491  convertParameterAttrs(function, argIdx, argAttrs);
1492  if (failed(attrBuilder))
1493  return failure();
1494  llvmArg.addAttrs(*attrBuilder);
1495  }
1496  }
1497 
1498  // Forward the pass-through attributes to LLVM.
1500  function.getLoc(), function.getPassthrough(), llvmFunc)))
1501  return failure();
1502 
1503  // Convert visibility attribute.
1504  llvmFunc->setVisibility(convertVisibilityToLLVM(function.getVisibility_()));
1505 
1506  // Convert the comdat attribute.
1507  if (std::optional<mlir::SymbolRefAttr> comdat = function.getComdat()) {
1508  auto selectorOp = cast<ComdatSelectorOp>(
1509  SymbolTable::lookupNearestSymbolFrom(function, *comdat));
1510  llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1511  }
1512 
1513  if (auto gc = function.getGarbageCollector())
1514  llvmFunc->setGC(gc->str());
1515 
1516  if (auto unnamedAddr = function.getUnnamedAddr())
1517  llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1518 
1519  if (auto alignment = function.getAlignment())
1520  llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1521 
1522  // Translate the debug information for this function.
1523  debugTranslation->translate(function, *llvmFunc);
1524  }
1525 
1526  return success();
1527 }
1528 
1529 LogicalResult ModuleTranslation::convertFunctions() {
1530  // Convert functions.
1531  for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1532  // Do not convert external functions, but do process dialect attributes
1533  // attached to them.
1534  if (function.isExternal()) {
1535  if (failed(convertDialectAttributes(function, {})))
1536  return failure();
1537  continue;
1538  }
1539 
1540  if (failed(convertOneFunction(function)))
1541  return failure();
1542  }
1543 
1544  return success();
1545 }
1546 
1547 LogicalResult ModuleTranslation::convertComdats() {
1548  for (auto comdatOp : getModuleBody(mlirModule).getOps<ComdatOp>()) {
1549  for (auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1550  llvm::Module *module = getLLVMModule();
1551  if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1552  return emitError(selectorOp.getLoc())
1553  << "comdat selection symbols must be unique even in different "
1554  "comdat regions";
1555  llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1556  comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1557  comdatMapping.try_emplace(selectorOp, comdat);
1558  }
1559  }
1560  return success();
1561 }
1562 
1563 void ModuleTranslation::setAccessGroupsMetadata(AccessGroupOpInterface op,
1564  llvm::Instruction *inst) {
1565  if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1566  inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1567 }
1568 
1569 llvm::MDNode *
1570 ModuleTranslation::getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr) {
1571  auto [scopeIt, scopeInserted] =
1572  aliasScopeMetadataMapping.try_emplace(aliasScopeAttr, nullptr);
1573  if (!scopeInserted)
1574  return scopeIt->second;
1575  llvm::LLVMContext &ctx = llvmModule->getContext();
1576  auto dummy = llvm::MDNode::getTemporary(ctx, std::nullopt);
1577  // Convert the domain metadata node if necessary.
1578  auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
1579  aliasScopeAttr.getDomain(), nullptr);
1580  if (insertedDomain) {
1582  // Placeholder for self-reference.
1583  operands.push_back(dummy.get());
1584  if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
1585  operands.push_back(llvm::MDString::get(ctx, description));
1586  domainIt->second = llvm::MDNode::get(ctx, operands);
1587  // Self-reference for uniqueness.
1588  domainIt->second->replaceOperandWith(0, domainIt->second);
1589  }
1590  // Convert the scope metadata node.
1591  assert(domainIt->second && "Scope's domain should already be valid");
1593  // Placeholder for self-reference.
1594  operands.push_back(dummy.get());
1595  operands.push_back(domainIt->second);
1596  if (StringAttr description = aliasScopeAttr.getDescription())
1597  operands.push_back(llvm::MDString::get(ctx, description));
1598  scopeIt->second = llvm::MDNode::get(ctx, operands);
1599  // Self-reference for uniqueness.
1600  scopeIt->second->replaceOperandWith(0, scopeIt->second);
1601  return scopeIt->second;
1602 }
1603 
1605  ArrayRef<AliasScopeAttr> aliasScopeAttrs) {
1607  nodes.reserve(aliasScopeAttrs.size());
1608  for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
1609  nodes.push_back(getOrCreateAliasScope(aliasScopeAttr));
1610  return llvm::MDNode::get(getLLVMContext(), nodes);
1611 }
1612 
1613 void ModuleTranslation::setAliasScopeMetadata(AliasAnalysisOpInterface op,
1614  llvm::Instruction *inst) {
1615  auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs, unsigned kind) {
1616  if (!aliasScopeAttrs || aliasScopeAttrs.empty())
1617  return;
1618  llvm::MDNode *node = getOrCreateAliasScopes(
1619  llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
1620  inst->setMetadata(kind, node);
1621  };
1622 
1623  populateScopeMetadata(op.getAliasScopesOrNull(),
1624  llvm::LLVMContext::MD_alias_scope);
1625  populateScopeMetadata(op.getNoAliasScopesOrNull(),
1626  llvm::LLVMContext::MD_noalias);
1627 }
1628 
1629 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr) const {
1630  return tbaaMetadataMapping.lookup(tbaaAttr);
1631 }
1632 
1633 void ModuleTranslation::setTBAAMetadata(AliasAnalysisOpInterface op,
1634  llvm::Instruction *inst) {
1635  ArrayAttr tagRefs = op.getTBAATagsOrNull();
1636  if (!tagRefs || tagRefs.empty())
1637  return;
1638 
1639  // LLVM IR currently does not support attaching more than one TBAA access tag
1640  // to a memory accessing instruction. It may be useful to support this in
1641  // future, but for the time being just ignore the metadata if MLIR operation
1642  // has multiple access tags.
1643  if (tagRefs.size() > 1) {
1644  op.emitWarning() << "TBAA access tags were not translated, because LLVM "
1645  "IR only supports a single tag per instruction";
1646  return;
1647  }
1648 
1649  llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
1650  inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
1651 }
1652 
1653 void ModuleTranslation::setBranchWeightsMetadata(BranchWeightOpInterface op) {
1654  DenseI32ArrayAttr weightsAttr = op.getBranchWeightsOrNull();
1655  if (!weightsAttr)
1656  return;
1657 
1658  llvm::Instruction *inst = isa<CallOp>(op) ? lookupCall(op) : lookupBranch(op);
1659  assert(inst && "expected the operation to have a mapping to an instruction");
1660  SmallVector<uint32_t> weights(weightsAttr.asArrayRef());
1661  inst->setMetadata(
1662  llvm::LLVMContext::MD_prof,
1663  llvm::MDBuilder(getLLVMContext()).createBranchWeights(weights));
1664 }
1665 
1666 LogicalResult ModuleTranslation::createTBAAMetadata() {
1667  llvm::LLVMContext &ctx = llvmModule->getContext();
1668  llvm::IntegerType *offsetTy = llvm::IntegerType::get(ctx, 64);
1669 
1670  // Walk the entire module and create all metadata nodes for the TBAA
1671  // attributes. The code below relies on two invariants of the
1672  // `AttrTypeWalker`:
1673  // 1. Attributes are visited in post-order: Since the attributes create a DAG,
1674  // this ensures that any lookups into `tbaaMetadataMapping` for child
1675  // attributes succeed.
1676  // 2. Attributes are only ever visited once: This way we don't leak any
1677  // LLVM metadata instances.
1678  AttrTypeWalker walker;
1679  walker.addWalk([&](TBAARootAttr root) {
1680  tbaaMetadataMapping.insert(
1681  {root, llvm::MDNode::get(ctx, llvm::MDString::get(ctx, root.getId()))});
1682  });
1683 
1684  walker.addWalk([&](TBAATypeDescriptorAttr descriptor) {
1686  operands.push_back(llvm::MDString::get(ctx, descriptor.getId()));
1687  for (TBAAMemberAttr member : descriptor.getMembers()) {
1688  operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
1689  operands.push_back(llvm::ConstantAsMetadata::get(
1690  llvm::ConstantInt::get(offsetTy, member.getOffset())));
1691  }
1692 
1693  tbaaMetadataMapping.insert({descriptor, llvm::MDNode::get(ctx, operands)});
1694  });
1695 
1696  walker.addWalk([&](TBAATagAttr tag) {
1698 
1699  operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
1700  operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
1701 
1702  operands.push_back(llvm::ConstantAsMetadata::get(
1703  llvm::ConstantInt::get(offsetTy, tag.getOffset())));
1704  if (tag.getConstant())
1705  operands.push_back(
1707 
1708  tbaaMetadataMapping.insert({tag, llvm::MDNode::get(ctx, operands)});
1709  });
1710 
1711  mlirModule->walk([&](AliasAnalysisOpInterface analysisOpInterface) {
1712  if (auto attr = analysisOpInterface.getTBAATagsOrNull())
1713  walker.walk(attr);
1714  });
1715 
1716  return success();
1717 }
1718 
1720  llvm::Instruction *inst) {
1721  LoopAnnotationAttr attr =
1723  .Case<LLVM::BrOp, LLVM::CondBrOp>(
1724  [](auto branchOp) { return branchOp.getLoopAnnotationAttr(); });
1725  if (!attr)
1726  return;
1727  llvm::MDNode *loopMD =
1728  loopAnnotationTranslation->translateLoopAnnotation(attr, op);
1729  inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
1730 }
1731 
1733  return typeTranslator.translateType(type);
1734 }
1735 
1736 /// A helper to look up remapped operands in the value remapping table.
1738  SmallVector<llvm::Value *> remapped;
1739  remapped.reserve(values.size());
1740  for (Value v : values)
1741  remapped.push_back(lookupValue(v));
1742  return remapped;
1743 }
1744 
1745 llvm::OpenMPIRBuilder *ModuleTranslation::getOpenMPBuilder() {
1746  if (!ompBuilder) {
1747  ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
1748  ompBuilder->initialize();
1749 
1750  // Flags represented as top-level OpenMP dialect attributes are set in
1751  // `OpenMPDialectLLVMIRTranslationInterface::amendOperation()`. Here we set
1752  // the default configuration.
1753  ompBuilder->setConfig(llvm::OpenMPIRBuilderConfig(
1754  /* IsTargetDevice = */ false, /* IsGPU = */ false,
1755  /* OpenMPOffloadMandatory = */ false,
1756  /* HasRequiresReverseOffload = */ false,
1757  /* HasRequiresUnifiedAddress = */ false,
1758  /* HasRequiresUnifiedSharedMemory = */ false,
1759  /* HasRequiresDynamicAllocators = */ false));
1760  }
1761  return ompBuilder.get();
1762 }
1763 
1765  llvm::DILocalScope *scope) {
1766  return debugTranslation->translateLoc(loc, scope);
1767 }
1768 
1769 llvm::DIExpression *
1770 ModuleTranslation::translateExpression(LLVM::DIExpressionAttr attr) {
1771  return debugTranslation->translateExpression(attr);
1772 }
1773 
1774 llvm::DIGlobalVariableExpression *
1776  LLVM::DIGlobalVariableExpressionAttr attr) {
1777  return debugTranslation->translateGlobalVariableExpression(attr);
1778 }
1779 
1781  return debugTranslation->translate(attr);
1782 }
1783 
1784 llvm::RoundingMode
1785 ModuleTranslation::translateRoundingMode(LLVM::RoundingMode rounding) {
1786  return convertRoundingModeToLLVM(rounding);
1787 }
1788 
1790  LLVM::FPExceptionBehavior exceptionBehavior) {
1791  return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
1792 }
1793 
1794 llvm::NamedMDNode *
1796  return llvmModule->getOrInsertNamedMetadata(name);
1797 }
1798 
1799 void ModuleTranslation::StackFrame::anchor() {}
1800 
1801 static std::unique_ptr<llvm::Module>
1802 prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
1803  StringRef name) {
1804  m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
1805  auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
1806  // ModuleTranslation can currently only construct modules in the old debug
1807  // info format, so set the flag accordingly.
1808  llvmModule->setNewDbgInfoFormatFlag(false);
1809  if (auto dataLayoutAttr =
1810  m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
1811  llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
1812  } else {
1813  FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(""));
1814  if (auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
1815  if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
1816  llvmDataLayout =
1817  translateDataLayout(spec, DataLayout(iface), m->getLoc());
1818  }
1819  } else if (auto mod = dyn_cast<ModuleOp>(m)) {
1820  if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
1821  llvmDataLayout =
1822  translateDataLayout(spec, DataLayout(mod), m->getLoc());
1823  }
1824  }
1825  if (failed(llvmDataLayout))
1826  return nullptr;
1827  llvmModule->setDataLayout(*llvmDataLayout);
1828  }
1829  if (auto targetTripleAttr =
1830  m->getDiscardableAttr(LLVM::LLVMDialect::getTargetTripleAttrName()))
1831  llvmModule->setTargetTriple(cast<StringAttr>(targetTripleAttr).getValue());
1832 
1833  return llvmModule;
1834 }
1835 
1836 std::unique_ptr<llvm::Module>
1837 mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
1838  StringRef name, bool disableVerification) {
1839  if (!satisfiesLLVMModule(module)) {
1840  module->emitOpError("can not be translated to an LLVMIR module");
1841  return nullptr;
1842  }
1843 
1844  std::unique_ptr<llvm::Module> llvmModule =
1845  prepareLLVMModule(module, llvmContext, name);
1846  if (!llvmModule)
1847  return nullptr;
1848 
1851 
1852  ModuleTranslation translator(module, std::move(llvmModule));
1853  llvm::IRBuilder<> llvmBuilder(llvmContext);
1854 
1855  // Convert module before functions and operations inside, so dialect
1856  // attributes can be used to change dialect-specific global configurations via
1857  // `amendOperation()`. These configurations can then influence the translation
1858  // of operations afterwards.
1859  if (failed(translator.convertOperation(*module, llvmBuilder)))
1860  return nullptr;
1861 
1862  if (failed(translator.convertComdats()))
1863  return nullptr;
1864  if (failed(translator.convertFunctionSignatures()))
1865  return nullptr;
1866  if (failed(translator.convertGlobals()))
1867  return nullptr;
1868  if (failed(translator.createTBAAMetadata()))
1869  return nullptr;
1870 
1871  // Convert other top-level operations if possible.
1872  for (Operation &o : getModuleBody(module).getOperations()) {
1873  if (!isa<LLVM::LLVMFuncOp, LLVM::GlobalOp, LLVM::GlobalCtorsOp,
1874  LLVM::GlobalDtorsOp, LLVM::ComdatOp>(&o) &&
1875  !o.hasTrait<OpTrait::IsTerminator>() &&
1876  failed(translator.convertOperation(o, llvmBuilder))) {
1877  return nullptr;
1878  }
1879  }
1880 
1881  // Operations in function bodies with symbolic references must be converted
1882  // after the top-level operations they refer to are declared, so we do it
1883  // last.
1884  if (failed(translator.convertFunctions()))
1885  return nullptr;
1886 
1887  // Once we've finished constructing elements in the module, we should convert
1888  // it to use the debug info format desired by LLVM.
1889  // See https://llvm.org/docs/RemoveDIsDebugInfo.html
1890  translator.llvmModule->setIsNewDbgInfoFormat(UseNewDbgInfoFormat);
1891 
1892  if (!disableVerification &&
1893  llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
1894  return nullptr;
1895 
1896  return std::move(translator.llvmModule);
1897 }
static MLIRContext * getContext(OpFoldResult val)
@ None
static Value getPHISourceValue(Block *current, Block *pred, unsigned numArguments, unsigned index)
Get the SSA value passed to the current block from the terminator operation of its predecessor.
static llvm::Constant * convertDenseElementsAttr(Location loc, DenseElementsAttr denseElementsAttr, llvm::Type *llvmType, const ModuleTranslation &moduleTranslation)
Convert a dense elements attribute to an LLVM IR constant using its raw data storage if possible.
static Block & getModuleBody(Operation *module)
A helper method to get the single Block in an operation honoring LLVM's module requirements.
static void addRuntimePreemptionSpecifier(bool dsoLocalRequested, llvm::GlobalValue *gv)
Sets the runtime preemption specifier of gv to dso_local if dsoLocalRequested is true,...
static LogicalResult checkedAddLLVMFnAttribute(Location loc, llvm::Function *llvmFunc, StringRef key, StringRef value=StringRef())
Attempts to add an attribute identified by key, optionally with the given value to LLVM function llvm...
static void convertFunctionAttributes(LLVMFuncOp func, llvm::Function *llvmFunc)
Converts function attributes from func and attaches them to llvmFunc.
llvm::cl::opt< bool > UseNewDbgInfoFormat
static bool shouldDropGlobalInitializer(llvm::GlobalValue::LinkageTypes linkage, llvm::Constant *cst)
A helper method to decide if a constant must not be set as a global variable initializer.
static llvm::Type * getInnermostElementType(llvm::Type *type)
Returns the first non-sequential type nested in sequential types.
static std::unique_ptr< llvm::Module > prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext, StringRef name)
static llvm::Constant * convertDenseResourceElementsAttr(Location loc, DenseResourceElementsAttr denseResourceAttr, llvm::Type *llvmType, const ModuleTranslation &moduleTranslation)
Convert a dense resource elements attribute to an LLVM IR constant using its raw data storage if poss...
static void convertFunctionMemoryAttributes(LLVMFuncOp func, llvm::Function *llvmFunc)
Converts memory effect attributes from func and attaches them to llvmFunc.
static LogicalResult forwardPassthroughAttributes(Location loc, std::optional< ArrayAttr > attributes, llvm::Function *llvmFunc)
Attaches the attributes listed in the given array attribute to llvmFunc.
static llvm::Constant * buildSequentialConstant(ArrayRef< llvm::Constant * > &constants, ArrayRef< int64_t > shape, llvm::Type *type, Location loc)
Builds a constant of a sequential LLVM type type, potentially containing other sequential types recur...
The following classes enable support for parsing and printing resources within MLIR assembly formats.
Definition: AsmState.h:88
ArrayRef< char > getData() const
Return the raw underlying data of this blob.
Definition: AsmState.h:142
void addWalk(WalkFn< Attribute > &&fn)
Register a walk function for a given attribute or type.
WalkResult walk(T element)
Walk the given attribute/type, and recursively walk any sub elements.
Attributes are known-constant values of operations.
Definition: Attributes.h:25
Block represents an ordered list of Operations.
Definition: Block.h:31
Operation * getTerminator()
Get the terminator operation of this block.
Definition: Block.cpp:243
iterator_range< pred_iterator > getPredecessors()
Definition: Block.h:235
BlockArgListType getArguments()
Definition: Block.h:85
Operation & front()
Definition: Block.h:151
The main mechanism for performing data layout queries.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
uint64_t getTypePreferredAlignment(Type t) const
Returns the preferred of the given type in the current scope.
uint64_t getTypeABIAlignment(Type t) const
Returns the required alignment of the given type in the current scope.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
An attribute that represents a reference to a dense vector or tensor object.
std::enable_if_t<!std::is_base_of< Attribute, T >::value||std::is_same< Attribute, T >::value, T > getSplatValue() const
Return the splat value for this attribute.
int64_t getNumElements() const
Returns the number of elements held by this attribute.
bool isSplat() const
Returns true if this attribute corresponds to a splat, i.e.
ArrayRef< char > getRawData() const
Return the raw storage data held by this attribute.
ShapedType getType() const
Return the type of this ElementsAttr, guaranteed to be a vector or tensor with static shape.
const InterfaceType * getInterfaceFor(Object *obj) const
Get the interface for a given object, or null if one is not registered.
This class provides support for representing a failure result, or a valid value of type T.
Definition: LogicalResult.h:78
Base class for dialect interfaces providing translation to LLVM IR.
virtual LogicalResult convertOperation(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) const
Hook for derived dialect interface to provide translation of the operations to LLVM IR.
virtual LogicalResult convertParameterAttr(LLVM::LLVMFuncOp function, int argIdx, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation) const
Acts on the given function operation using the interface implemented by the dialect of one of the fun...
virtual LogicalResult amendOperation(Operation *op, ArrayRef< llvm::Instruction * > instructions, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation) const
Acts on the given operation using the interface implemented by the dialect of one of the operation's ...
This class represents the base attribute for all debug info attributes.
Definition: LLVMAttrs.h:27
Implementation class for module translation.
llvm::fp::ExceptionBehavior translateFPExceptionBehavior(LLVM::FPExceptionBehavior exceptionBehavior)
Translates the given LLVM FP exception behavior metadata.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
llvm::DIGlobalVariableExpression * translateGlobalVariableExpression(LLVM::DIGlobalVariableExpressionAttr attr)
Translates the given LLVM global variable expression metadata.
llvm::NamedMDNode * getOrInsertNamedModuleMetadata(StringRef name)
Gets the named metadata in the LLVM IR module being constructed, creating it if it does not exist.
llvm::Instruction * lookupBranch(Operation *op) const
Finds an LLVM IR instruction that corresponds to the given MLIR operation with successors.
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
void mapFunction(StringRef name, llvm::Function *func)
Stores the mapping between a function name and its LLVM IR representation.
llvm::DILocation * translateLoc(Location loc, llvm::DILocalScope *scope)
Translates the given location.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
void setBranchWeightsMetadata(BranchWeightOpInterface op)
Sets LLVM profiling metadata for operations that have branch weights.
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::RoundingMode translateRoundingMode(LLVM::RoundingMode rounding)
Translates the given LLVM rounding mode metadata.
void setTBAAMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
Sets LLVM TBAA metadata for memory operations that have TBAA attributes.
llvm::DIExpression * translateExpression(LLVM::DIExpressionAttr attr)
Translates the given LLVM DWARF expression metadata.
llvm::OpenMPIRBuilder * getOpenMPBuilder()
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
llvm::CallInst * lookupCall(Operation *op) const
Finds an LLVM call instruction that corresponds to the given MLIR call operation.
llvm::Metadata * translateDebugInfo(LLVM::DINodeAttr attr)
Translates the given LLVM debug info metadata.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
llvm::MDNode * getOrCreateAliasScopes(ArrayRef< AliasScopeAttr > aliasScopeAttrs)
Returns the LLVM metadata corresponding to an array of mlir LLVM dialect alias scope attributes.
void mapBlock(Block *mlir, llvm::BasicBlock *llvm)
Stores the mapping between an MLIR block and LLVM IR basic block.
llvm::MDNode * getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr)
Returns the LLVM metadata corresponding to a mlir LLVM dialect alias scope attribute.
void forgetMapping(Region &region)
Removes the mapping for blocks contained in the region and values defined in these blocks.
void setAliasScopeMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
void setAccessGroupsMetadata(AccessGroupOpInterface op, llvm::Instruction *inst)
void mapValue(Value mlir, llvm::Value *llvm)
Stores the mapping between an MLIR value and its LLVM IR counterpart.
void setLoopMetadata(Operation *op, llvm::Instruction *inst)
Sets LLVM loop metadata for branch operations that have a loop annotation attribute.
llvm::Type * translateType(Type type)
Translates the given MLIR LLVM dialect type to LLVM IR.
Definition: TypeToLLVM.cpp:192
A helper class that converts LoopAnnotationAttrs and AccessGroupAttrs into corresponding llvm::MDNode...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
Definition: MLIRContext.h:97
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:207
This class provides the API for ops that are known to be terminators.
Definition: OpDefinition.h:764
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
Attribute getDiscardableAttr(StringRef name)
Access a discardable attribute by name, returns an null Attribute if the discardable attribute does n...
Definition: Operation.h:448
Value getOperand(unsigned idx)
Definition: Operation.h:345
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Definition: Operation.h:529
Block * getSuccessor(unsigned index)
Definition: Operation.h:704
unsigned getNumSuccessors()
Definition: Operation.h:702
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
Definition: Operation.cpp:280
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition: Operation.h:402
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Definition: Operation.h:793
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:216
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:268
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Definition: Operation.h:682
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition: Operation.h:672
OperationName getName()
The name of an operation is the key identifier for it.
Definition: Operation.h:119
dialect_attr_range getDialectAttrs()
Return a range corresponding to the dialect attributes for this operation.
Definition: Operation.h:632
bool hasSuccessors()
Definition: Operation.h:701
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition: Operation.h:373
result_range getResults()
Definition: Operation.h:410
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
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
Block & front()
Definition: Region.h:65
This class models how operands are forwarded to block arguments in control flow.
bool empty() const
Returns true if there are no successor operands.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:381
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
use_iterator use_end() const
Definition: Value.h:209
Type getType() const
Return the type of this value.
Definition: Value.h:129
use_iterator use_begin() const
Definition: Value.h:208
Include the generated interface declarations.
Definition: CallGraph.h:229
void connectPHINodes(Region &region, const ModuleTranslation &state)
For all blocks in the region that were converted to LLVM IR using the given ModuleTranslation,...
llvm::CallInst * createIntrinsicCall(llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic, ArrayRef< llvm::Value * > args={}, ArrayRef< llvm::Type * > tys={})
Creates a call to an LLVM IR intrinsic function with the given arguments.
static llvm::DenseMap< llvm::StringRef, llvm::Attribute::AttrKind > getAttrNameToKindMapping()
Returns a dense map from LLVM attribute name to their kind in LLVM IR dialect.
llvm::Constant * getLLVMConstant(llvm::Type *llvmType, Attribute attr, Location loc, const ModuleTranslation &moduleTranslation)
Create an LLVM IR constant of llvmType from the MLIR attribute attr.
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
void legalizeDIExpressionsRecursively(Operation *op)
Register all known legalization patterns declared here and apply them to all ops in op.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:858
void ensureDistinctSuccessors(Operation *op)
Make argument-taking successors of each block distinct.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:285
DictionaryAttr getArgAttrDict(FunctionOpInterface op, unsigned index)
Returns the dictionary attribute corresponding to the argument at 'index'.
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
std::unique_ptr< llvm::Module > translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext, llvm::StringRef name="LLVMDialectModule", bool disableVerification=false)
Translates a given LLVM dialect module into an LLVM IR module living in the given context.
SetVector< Block * > getBlocksSortedByDominance(Region &region)
Gets a list of blocks that is sorted according to dominance.
DataLayoutSpecInterface translateDataLayout(const llvm::DataLayout &dataLayout, MLIRContext *context)
Translate the given LLVM data layout into an MLIR equivalent using the DLTI dialect.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Definition: Utils.cpp:305
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26