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