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