MLIR  22.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"
26 #include "mlir/IR/Attributes.h"
27 #include "mlir/IR/BuiltinOps.h"
28 #include "mlir/IR/BuiltinTypes.h"
30 #include "mlir/Support/LLVM.h"
33 
34 #include "llvm/ADT/STLExtras.h"
35 #include "llvm/ADT/StringExtras.h"
36 #include "llvm/ADT/TypeSwitch.h"
37 #include "llvm/Analysis/TargetFolder.h"
38 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
39 #include "llvm/IR/BasicBlock.h"
40 #include "llvm/IR/CFG.h"
41 #include "llvm/IR/Constants.h"
42 #include "llvm/IR/DerivedTypes.h"
43 #include "llvm/IR/IRBuilder.h"
44 #include "llvm/IR/InlineAsm.h"
45 #include "llvm/IR/LLVMContext.h"
46 #include "llvm/IR/MDBuilder.h"
47 #include "llvm/IR/Module.h"
48 #include "llvm/IR/Verifier.h"
49 #include "llvm/Support/Debug.h"
50 #include "llvm/Support/ErrorHandling.h"
51 #include "llvm/Support/raw_ostream.h"
52 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
53 #include "llvm/Transforms/Utils/Cloning.h"
54 #include "llvm/Transforms/Utils/ModuleUtils.h"
55 #include <numeric>
56 #include <optional>
57 
58 #define DEBUG_TYPE "llvm-dialect-to-llvm-ir"
59 
60 using namespace mlir;
61 using namespace mlir::LLVM;
62 using namespace mlir::LLVM::detail;
63 
64 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
65 
66 namespace {
67 /// A customized inserter for LLVM's IRBuilder that captures all LLVM IR
68 /// instructions that are created for future reference.
69 ///
70 /// This is intended to be used with the `CollectionScope` RAII object:
71 ///
72 /// llvm::IRBuilder<..., InstructionCapturingInserter> builder;
73 /// {
74 /// InstructionCapturingInserter::CollectionScope scope(builder);
75 /// // Call IRBuilder methods as usual.
76 ///
77 /// // This will return a list of all instructions created by the builder,
78 /// // in order of creation.
79 /// builder.getInserter().getCapturedInstructions();
80 /// }
81 /// // This will return an empty list.
82 /// builder.getInserter().getCapturedInstructions();
83 ///
84 /// The capturing functionality is _disabled_ by default for performance
85 /// consideration. It needs to be explicitly enabled, which is achieved by
86 /// creating a `CollectionScope`.
87 class InstructionCapturingInserter : public llvm::IRBuilderCallbackInserter {
88 public:
89  /// Constructs the inserter.
90  InstructionCapturingInserter()
91  : llvm::IRBuilderCallbackInserter([this](llvm::Instruction *instruction) {
92  if (LLVM_LIKELY(enabled))
93  capturedInstructions.push_back(instruction);
94  }) {}
95 
96  /// Returns the list of LLVM IR instructions captured since the last cleanup.
97  ArrayRef<llvm::Instruction *> getCapturedInstructions() const {
98  return capturedInstructions;
99  }
100 
101  /// Clears the list of captured LLVM IR instructions.
102  void clearCapturedInstructions() { capturedInstructions.clear(); }
103 
104  /// RAII object enabling the capture of created LLVM IR instructions.
105  class CollectionScope {
106  public:
107  /// Creates the scope for the given inserter.
108  CollectionScope(llvm::IRBuilderBase &irBuilder, bool isBuilderCapturing);
109 
110  /// Ends the scope.
111  ~CollectionScope();
112 
113  ArrayRef<llvm::Instruction *> getCapturedInstructions() {
114  if (!inserter)
115  return {};
116  return inserter->getCapturedInstructions();
117  }
118 
119  private:
120  /// Back reference to the inserter.
121  InstructionCapturingInserter *inserter = nullptr;
122 
123  /// List of instructions in the inserter prior to this scope.
124  SmallVector<llvm::Instruction *> previouslyCollectedInstructions;
125 
126  /// Whether the inserter was enabled prior to this scope.
127  bool wasEnabled;
128  };
129 
130  /// Enable or disable the capturing mechanism.
131  void setEnabled(bool enabled = true) { this->enabled = enabled; }
132 
133 private:
134  /// List of captured instructions.
135  SmallVector<llvm::Instruction *> capturedInstructions;
136 
137  /// Whether the collection is enabled.
138  bool enabled = false;
139 };
140 
141 using CapturingIRBuilder =
142  llvm::IRBuilder<llvm::TargetFolder, InstructionCapturingInserter>;
143 } // namespace
144 
145 InstructionCapturingInserter::CollectionScope::CollectionScope(
146  llvm::IRBuilderBase &irBuilder, bool isBuilderCapturing) {
147 
148  if (!isBuilderCapturing)
149  return;
150 
151  auto &capturingIRBuilder = static_cast<CapturingIRBuilder &>(irBuilder);
152  inserter = &capturingIRBuilder.getInserter();
153  wasEnabled = inserter->enabled;
154  if (wasEnabled)
155  previouslyCollectedInstructions.swap(inserter->capturedInstructions);
156  inserter->setEnabled(true);
157 }
158 
159 InstructionCapturingInserter::CollectionScope::~CollectionScope() {
160  if (!inserter)
161  return;
162 
163  previouslyCollectedInstructions.swap(inserter->capturedInstructions);
164  // If collection was enabled (likely in another, surrounding scope), keep
165  // the instructions collected in this scope.
166  if (wasEnabled) {
167  llvm::append_range(inserter->capturedInstructions,
168  previouslyCollectedInstructions);
169  }
170  inserter->setEnabled(wasEnabled);
171 }
172 
173 /// Translates the given data layout spec attribute to the LLVM IR data layout.
174 /// Only integer, float, pointer and endianness entries are currently supported.
175 static FailureOr<llvm::DataLayout>
176 translateDataLayout(DataLayoutSpecInterface attribute,
177  const DataLayout &dataLayout,
178  std::optional<Location> loc = std::nullopt) {
179  if (!loc)
180  loc = UnknownLoc::get(attribute.getContext());
181 
182  // Translate the endianness attribute.
183  std::string llvmDataLayout;
184  llvm::raw_string_ostream layoutStream(llvmDataLayout);
185  for (DataLayoutEntryInterface entry : attribute.getEntries()) {
186  auto key = llvm::dyn_cast_if_present<StringAttr>(entry.getKey());
187  if (!key)
188  continue;
189  if (key.getValue() == DLTIDialect::kDataLayoutEndiannessKey) {
190  auto value = cast<StringAttr>(entry.getValue());
191  bool isLittleEndian =
192  value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle;
193  layoutStream << "-" << (isLittleEndian ? "e" : "E");
194  continue;
195  }
196  if (key.getValue() == DLTIDialect::kDataLayoutManglingModeKey) {
197  auto value = cast<StringAttr>(entry.getValue());
198  layoutStream << "-m:" << value.getValue();
199  continue;
200  }
201  if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
202  auto value = cast<IntegerAttr>(entry.getValue());
203  uint64_t space = value.getValue().getZExtValue();
204  // Skip the default address space.
205  if (space == 0)
206  continue;
207  layoutStream << "-P" << space;
208  continue;
209  }
210  if (key.getValue() == DLTIDialect::kDataLayoutGlobalMemorySpaceKey) {
211  auto value = cast<IntegerAttr>(entry.getValue());
212  uint64_t space = value.getValue().getZExtValue();
213  // Skip the default address space.
214  if (space == 0)
215  continue;
216  layoutStream << "-G" << space;
217  continue;
218  }
219  if (key.getValue() == DLTIDialect::kDataLayoutAllocaMemorySpaceKey) {
220  auto value = cast<IntegerAttr>(entry.getValue());
221  uint64_t space = value.getValue().getZExtValue();
222  // Skip the default address space.
223  if (space == 0)
224  continue;
225  layoutStream << "-A" << space;
226  continue;
227  }
228  if (key.getValue() == DLTIDialect::kDataLayoutStackAlignmentKey) {
229  auto value = cast<IntegerAttr>(entry.getValue());
230  uint64_t alignment = value.getValue().getZExtValue();
231  // Skip the default stack alignment.
232  if (alignment == 0)
233  continue;
234  layoutStream << "-S" << alignment;
235  continue;
236  }
237  if (key.getValue() == DLTIDialect::kDataLayoutFunctionPointerAlignmentKey) {
238  auto value = cast<FunctionPointerAlignmentAttr>(entry.getValue());
239  uint64_t alignment = value.getAlignment();
240  // Skip the default function pointer alignment.
241  if (alignment == 0)
242  continue;
243  layoutStream << "-F" << (value.getFunctionDependent() ? "n" : "i")
244  << alignment;
245  continue;
246  }
247  if (key.getValue() == DLTIDialect::kDataLayoutLegalIntWidthsKey) {
248  layoutStream << "-n";
249  llvm::interleave(
250  cast<DenseI32ArrayAttr>(entry.getValue()).asArrayRef(), layoutStream,
251  [&](int32_t val) { layoutStream << val; }, ":");
252  continue;
253  }
254  emitError(*loc) << "unsupported data layout key " << key;
255  return failure();
256  }
257 
258  // Go through the list of entries to check which types are explicitly
259  // specified in entries. Where possible, data layout queries are used instead
260  // of directly inspecting the entries.
261  for (DataLayoutEntryInterface entry : attribute.getEntries()) {
262  auto type = llvm::dyn_cast_if_present<Type>(entry.getKey());
263  if (!type)
264  continue;
265  // Data layout for the index type is irrelevant at this point.
266  if (isa<IndexType>(type))
267  continue;
268  layoutStream << "-";
269  LogicalResult result =
271  .Case<IntegerType, Float16Type, Float32Type, Float64Type,
272  Float80Type, Float128Type>([&](Type type) -> LogicalResult {
273  if (auto intType = dyn_cast<IntegerType>(type)) {
274  if (intType.getSignedness() != IntegerType::Signless)
275  return emitError(*loc)
276  << "unsupported data layout for non-signless integer "
277  << intType;
278  layoutStream << "i";
279  } else {
280  layoutStream << "f";
281  }
282  uint64_t size = dataLayout.getTypeSizeInBits(type);
283  uint64_t abi = dataLayout.getTypeABIAlignment(type) * 8u;
284  uint64_t preferred =
285  dataLayout.getTypePreferredAlignment(type) * 8u;
286  layoutStream << size << ":" << abi;
287  if (abi != preferred)
288  layoutStream << ":" << preferred;
289  return success();
290  })
291  .Case([&](LLVMPointerType type) {
292  layoutStream << "p" << type.getAddressSpace() << ":";
293  uint64_t size = dataLayout.getTypeSizeInBits(type);
294  uint64_t abi = dataLayout.getTypeABIAlignment(type) * 8u;
295  uint64_t preferred =
296  dataLayout.getTypePreferredAlignment(type) * 8u;
297  uint64_t index = *dataLayout.getTypeIndexBitwidth(type);
298  layoutStream << size << ":" << abi << ":" << preferred << ":"
299  << index;
300  return success();
301  })
302  .Default([loc](Type type) {
303  return emitError(*loc)
304  << "unsupported type in data layout: " << type;
305  });
306  if (failed(result))
307  return failure();
308  }
309  StringRef layoutSpec(llvmDataLayout);
310  layoutSpec.consume_front("-");
311 
312  return llvm::DataLayout(layoutSpec);
313 }
314 
315 /// Builds a constant of a sequential LLVM type `type`, potentially containing
316 /// other sequential types recursively, from the individual constant values
317 /// provided in `constants`. `shape` contains the number of elements in nested
318 /// sequential types. Reports errors at `loc` and returns nullptr on error.
319 static llvm::Constant *
321  ArrayRef<int64_t> shape, llvm::Type *type,
322  Location loc) {
323  if (shape.empty()) {
324  llvm::Constant *result = constants.front();
325  constants = constants.drop_front();
326  return result;
327  }
328 
329  llvm::Type *elementType;
330  if (auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
331  elementType = arrayTy->getElementType();
332  } else if (auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
333  elementType = vectorTy->getElementType();
334  } else {
335  emitError(loc) << "expected sequential LLVM types wrapping a scalar";
336  return nullptr;
337  }
338 
340  nested.reserve(shape.front());
341  for (int64_t i = 0; i < shape.front(); ++i) {
342  nested.push_back(buildSequentialConstant(constants, shape.drop_front(),
343  elementType, loc));
344  if (!nested.back())
345  return nullptr;
346  }
347 
348  if (shape.size() == 1 && type->isVectorTy())
349  return llvm::ConstantVector::get(nested);
351  llvm::ArrayType::get(elementType, shape.front()), nested);
352 }
353 
354 /// Returns the first non-sequential type nested in sequential types.
355 static llvm::Type *getInnermostElementType(llvm::Type *type) {
356  do {
357  if (auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
358  type = arrayTy->getElementType();
359  } else if (auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
360  type = vectorTy->getElementType();
361  } else {
362  return type;
363  }
364  } while (true);
365 }
366 
367 /// Convert a dense elements attribute to an LLVM IR constant using its raw data
368 /// storage if possible. This supports elements attributes of tensor or vector
369 /// type and avoids constructing separate objects for individual values of the
370 /// innermost dimension. Constants for other dimensions are still constructed
371 /// recursively. Returns null if constructing from raw data is not supported for
372 /// this type, e.g., element type is not a power-of-two-sized primitive. Reports
373 /// other errors at `loc`.
374 static llvm::Constant *
376  llvm::Type *llvmType,
377  const ModuleTranslation &moduleTranslation) {
378  if (!denseElementsAttr)
379  return nullptr;
380 
381  llvm::Type *innermostLLVMType = getInnermostElementType(llvmType);
382  if (!llvm::ConstantDataSequential::isElementTypeCompatible(innermostLLVMType))
383  return nullptr;
384 
385  ShapedType type = denseElementsAttr.getType();
386  if (type.getNumElements() == 0)
387  return nullptr;
388 
389  // Check that the raw data size matches what is expected for the scalar size.
390  // TODO: in theory, we could repack the data here to keep constructing from
391  // raw data.
392  // TODO: we may also need to consider endianness when cross-compiling to an
393  // architecture where it is different.
394  int64_t elementByteSize = denseElementsAttr.getRawData().size() /
395  denseElementsAttr.getNumElements();
396  if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits())
397  return nullptr;
398 
399  // Compute the shape of all dimensions but the innermost. Note that the
400  // innermost dimension may be that of the vector element type.
401  bool hasVectorElementType = isa<VectorType>(type.getElementType());
402  int64_t numAggregates =
403  denseElementsAttr.getNumElements() /
404  (hasVectorElementType ? 1
405  : denseElementsAttr.getType().getShape().back());
406  ArrayRef<int64_t> outerShape = type.getShape();
407  if (!hasVectorElementType)
408  outerShape = outerShape.drop_back();
409 
410  // Handle the case of vector splat, LLVM has special support for it.
411  if (denseElementsAttr.isSplat() &&
412  (isa<VectorType>(type) || hasVectorElementType)) {
413  llvm::Constant *splatValue = LLVM::detail::getLLVMConstant(
414  innermostLLVMType, denseElementsAttr.getSplatValue<Attribute>(), loc,
415  moduleTranslation);
416  llvm::Constant *splatVector =
417  llvm::ConstantDataVector::getSplat(0, splatValue);
418  SmallVector<llvm::Constant *> constants(numAggregates, splatVector);
419  ArrayRef<llvm::Constant *> constantsRef = constants;
420  return buildSequentialConstant(constantsRef, outerShape, llvmType, loc);
421  }
422  if (denseElementsAttr.isSplat())
423  return nullptr;
424 
425  // In case of non-splat, create a constructor for the innermost constant from
426  // a piece of raw data.
427  std::function<llvm::Constant *(StringRef)> buildCstData;
428  if (isa<TensorType>(type)) {
429  auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
430  if (vectorElementType && vectorElementType.getRank() == 1) {
431  buildCstData = [&](StringRef data) {
432  return llvm::ConstantDataVector::getRaw(
433  data, vectorElementType.getShape().back(), innermostLLVMType);
434  };
435  } else if (!vectorElementType) {
436  buildCstData = [&](StringRef data) {
437  return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
438  innermostLLVMType);
439  };
440  }
441  } else if (isa<VectorType>(type)) {
442  buildCstData = [&](StringRef data) {
443  return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
444  innermostLLVMType);
445  };
446  }
447  if (!buildCstData)
448  return nullptr;
449 
450  // Create innermost constants and defer to the default constant creation
451  // mechanism for other dimensions.
453  int64_t aggregateSize = denseElementsAttr.getType().getShape().back() *
454  (innermostLLVMType->getScalarSizeInBits() / 8);
455  constants.reserve(numAggregates);
456  for (unsigned i = 0; i < numAggregates; ++i) {
457  StringRef data(denseElementsAttr.getRawData().data() + i * aggregateSize,
458  aggregateSize);
459  constants.push_back(buildCstData(data));
460  }
461 
462  ArrayRef<llvm::Constant *> constantsRef = constants;
463  return buildSequentialConstant(constantsRef, outerShape, llvmType, loc);
464 }
465 
466 /// Convert a dense resource elements attribute to an LLVM IR constant using its
467 /// raw data storage if possible. This supports elements attributes of tensor or
468 /// vector type and avoids constructing separate objects for individual values
469 /// of the innermost dimension. Constants for other dimensions are still
470 /// constructed recursively. Returns nullptr on failure and emits errors at
471 /// `loc`.
472 static llvm::Constant *convertDenseResourceElementsAttr(
473  Location loc, DenseResourceElementsAttr denseResourceAttr,
474  llvm::Type *llvmType, const ModuleTranslation &moduleTranslation) {
475  assert(denseResourceAttr && "expected non-null attribute");
476 
477  llvm::Type *innermostLLVMType = getInnermostElementType(llvmType);
478  if (!llvm::ConstantDataSequential::isElementTypeCompatible(
479  innermostLLVMType)) {
480  emitError(loc, "no known conversion for innermost element type");
481  return nullptr;
482  }
483 
484  ShapedType type = denseResourceAttr.getType();
485  assert(type.getNumElements() > 0 && "Expected non-empty elements attribute");
486 
487  AsmResourceBlob *blob = denseResourceAttr.getRawHandle().getBlob();
488  if (!blob) {
489  emitError(loc, "resource does not exist");
490  return nullptr;
491  }
492 
493  ArrayRef<char> rawData = blob->getData();
494 
495  // Check that the raw data size matches what is expected for the scalar size.
496  // TODO: in theory, we could repack the data here to keep constructing from
497  // raw data.
498  // TODO: we may also need to consider endianness when cross-compiling to an
499  // architecture where it is different.
500  int64_t numElements = denseResourceAttr.getType().getNumElements();
501  int64_t elementByteSize = rawData.size() / numElements;
502  if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits()) {
503  emitError(loc, "raw data size does not match element type size");
504  return nullptr;
505  }
506 
507  // Compute the shape of all dimensions but the innermost. Note that the
508  // innermost dimension may be that of the vector element type.
509  bool hasVectorElementType = isa<VectorType>(type.getElementType());
510  int64_t numAggregates =
511  numElements / (hasVectorElementType
512  ? 1
513  : denseResourceAttr.getType().getShape().back());
514  ArrayRef<int64_t> outerShape = type.getShape();
515  if (!hasVectorElementType)
516  outerShape = outerShape.drop_back();
517 
518  // Create a constructor for the innermost constant from a piece of raw data.
519  std::function<llvm::Constant *(StringRef)> buildCstData;
520  if (isa<TensorType>(type)) {
521  auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
522  if (vectorElementType && vectorElementType.getRank() == 1) {
523  buildCstData = [&](StringRef data) {
524  return llvm::ConstantDataVector::getRaw(
525  data, vectorElementType.getShape().back(), innermostLLVMType);
526  };
527  } else if (!vectorElementType) {
528  buildCstData = [&](StringRef data) {
529  return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
530  innermostLLVMType);
531  };
532  }
533  } else if (isa<VectorType>(type)) {
534  buildCstData = [&](StringRef data) {
535  return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
536  innermostLLVMType);
537  };
538  }
539  if (!buildCstData) {
540  emitError(loc, "unsupported dense_resource type");
541  return nullptr;
542  }
543 
544  // Create innermost constants and defer to the default constant creation
545  // mechanism for other dimensions.
547  int64_t aggregateSize = denseResourceAttr.getType().getShape().back() *
548  (innermostLLVMType->getScalarSizeInBits() / 8);
549  constants.reserve(numAggregates);
550  for (unsigned i = 0; i < numAggregates; ++i) {
551  StringRef data(rawData.data() + i * aggregateSize, aggregateSize);
552  constants.push_back(buildCstData(data));
553  }
554 
555  ArrayRef<llvm::Constant *> constantsRef = constants;
556  return buildSequentialConstant(constantsRef, outerShape, llvmType, loc);
557 }
558 
559 /// Create an LLVM IR constant of `llvmType` from the MLIR attribute `attr`.
560 /// This currently supports integer, floating point, splat and dense element
561 /// attributes and combinations thereof. Also, an array attribute with two
562 /// elements is supported to represent a complex constant. In case of error,
563 /// report it to `loc` and return nullptr.
565  llvm::Type *llvmType, Attribute attr, Location loc,
566  const ModuleTranslation &moduleTranslation) {
567  if (!attr || isa<UndefAttr>(attr))
568  return llvm::UndefValue::get(llvmType);
569  if (isa<ZeroAttr>(attr))
570  return llvm::Constant::getNullValue(llvmType);
571  if (auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
572  auto arrayAttr = dyn_cast<ArrayAttr>(attr);
573  if (!arrayAttr) {
574  emitError(loc, "expected an array attribute for a struct constant");
575  return nullptr;
576  }
577  SmallVector<llvm::Constant *> structElements;
578  structElements.reserve(structType->getNumElements());
579  for (auto [elemType, elemAttr] :
580  zip_equal(structType->elements(), arrayAttr)) {
581  llvm::Constant *element =
582  getLLVMConstant(elemType, elemAttr, loc, moduleTranslation);
583  if (!element)
584  return nullptr;
585  structElements.push_back(element);
586  }
587  return llvm::ConstantStruct::get(structType, structElements);
588  }
589  // For integer types, we allow a mismatch in sizes as the index type in
590  // MLIR might have a different size than the index type in the LLVM module.
591  if (auto intAttr = dyn_cast<IntegerAttr>(attr))
592  return llvm::ConstantInt::get(
593  llvmType,
594  intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth()));
595  if (auto floatAttr = dyn_cast<FloatAttr>(attr)) {
596  const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
597  // Special case for 8-bit floats, which are represented by integers due to
598  // the lack of native fp8 types in LLVM at the moment. Additionally, handle
599  // targets (like AMDGPU) that don't implement bfloat and convert all bfloats
600  // to i16.
601  unsigned floatWidth = APFloat::getSizeInBits(sem);
602  if (llvmType->isIntegerTy(floatWidth))
603  return llvm::ConstantInt::get(llvmType,
604  floatAttr.getValue().bitcastToAPInt());
605  if (llvmType !=
606  llvm::Type::getFloatingPointTy(llvmType->getContext(),
607  floatAttr.getValue().getSemantics())) {
608  emitError(loc, "FloatAttr does not match expected type of the constant");
609  return nullptr;
610  }
611  return llvm::ConstantFP::get(llvmType, floatAttr.getValue());
612  }
613  if (auto funcAttr = dyn_cast<FlatSymbolRefAttr>(attr))
614  return llvm::ConstantExpr::getBitCast(
615  moduleTranslation.lookupFunction(funcAttr.getValue()), llvmType);
616  if (auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
617  llvm::Type *elementType;
618  uint64_t numElements;
619  bool isScalable = false;
620  if (auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
621  elementType = arrayTy->getElementType();
622  numElements = arrayTy->getNumElements();
623  } else if (auto *fVectorTy = dyn_cast<llvm::FixedVectorType>(llvmType)) {
624  elementType = fVectorTy->getElementType();
625  numElements = fVectorTy->getNumElements();
626  } else if (auto *sVectorTy = dyn_cast<llvm::ScalableVectorType>(llvmType)) {
627  elementType = sVectorTy->getElementType();
628  numElements = sVectorTy->getMinNumElements();
629  isScalable = true;
630  } else {
631  llvm_unreachable("unrecognized constant vector type");
632  }
633  // Splat value is a scalar. Extract it only if the element type is not
634  // another sequence type. The recursion terminates because each step removes
635  // one outer sequential type.
636  bool elementTypeSequential =
637  isa<llvm::ArrayType, llvm::VectorType>(elementType);
638  llvm::Constant *child = getLLVMConstant(
639  elementType,
640  elementTypeSequential ? splatAttr
641  : splatAttr.getSplatValue<Attribute>(),
642  loc, moduleTranslation);
643  if (!child)
644  return nullptr;
645  if (llvmType->isVectorTy())
646  return llvm::ConstantVector::getSplat(
647  llvm::ElementCount::get(numElements, /*Scalable=*/isScalable), child);
648  if (llvmType->isArrayTy()) {
649  auto *arrayType = llvm::ArrayType::get(elementType, numElements);
650  if (child->isZeroValue()) {
651  return llvm::ConstantAggregateZero::get(arrayType);
652  } else {
653  if (llvm::ConstantDataSequential::isElementTypeCompatible(
654  elementType)) {
655  // TODO: Handle all compatible types. This code only handles integer.
656  if (isa<llvm::IntegerType>(elementType)) {
657  if (llvm::ConstantInt *ci = dyn_cast<llvm::ConstantInt>(child)) {
658  if (ci->getBitWidth() == 8) {
659  SmallVector<int8_t> constants(numElements, ci->getZExtValue());
660  return llvm::ConstantDataArray::get(elementType->getContext(),
661  constants);
662  }
663  if (ci->getBitWidth() == 16) {
664  SmallVector<int16_t> constants(numElements, ci->getZExtValue());
665  return llvm::ConstantDataArray::get(elementType->getContext(),
666  constants);
667  }
668  if (ci->getBitWidth() == 32) {
669  SmallVector<int32_t> constants(numElements, ci->getZExtValue());
670  return llvm::ConstantDataArray::get(elementType->getContext(),
671  constants);
672  }
673  if (ci->getBitWidth() == 64) {
674  SmallVector<int64_t> constants(numElements, ci->getZExtValue());
675  return llvm::ConstantDataArray::get(elementType->getContext(),
676  constants);
677  }
678  }
679  }
680  }
681  // std::vector is used here to accomodate large number of elements that
682  // exceed SmallVector capacity.
683  std::vector<llvm::Constant *> constants(numElements, child);
684  return llvm::ConstantArray::get(arrayType, constants);
685  }
686  }
687  }
688 
689  // Try using raw elements data if possible.
690  if (llvm::Constant *result =
691  convertDenseElementsAttr(loc, dyn_cast<DenseElementsAttr>(attr),
692  llvmType, moduleTranslation)) {
693  return result;
694  }
695 
696  if (auto denseResourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
697  return convertDenseResourceElementsAttr(loc, denseResourceAttr, llvmType,
698  moduleTranslation);
699  }
700 
701  // Fall back to element-by-element construction otherwise.
702  if (auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
703  assert(elementsAttr.getShapedType().hasStaticShape());
704  assert(!elementsAttr.getShapedType().getShape().empty() &&
705  "unexpected empty elements attribute shape");
706 
708  constants.reserve(elementsAttr.getNumElements());
709  llvm::Type *innermostType = getInnermostElementType(llvmType);
710  for (auto n : elementsAttr.getValues<Attribute>()) {
711  constants.push_back(
712  getLLVMConstant(innermostType, n, loc, moduleTranslation));
713  if (!constants.back())
714  return nullptr;
715  }
716  ArrayRef<llvm::Constant *> constantsRef = constants;
717  llvm::Constant *result = buildSequentialConstant(
718  constantsRef, elementsAttr.getShapedType().getShape(), llvmType, loc);
719  assert(constantsRef.empty() && "did not consume all elemental constants");
720  return result;
721  }
722 
723  if (auto stringAttr = dyn_cast<StringAttr>(attr)) {
724  return llvm::ConstantDataArray::get(moduleTranslation.getLLVMContext(),
725  ArrayRef<char>{stringAttr.getValue()});
726  }
727 
728  // Handle arrays of structs that cannot be represented as DenseElementsAttr
729  // in MLIR.
730  if (auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
731  if (auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
732  llvm::Type *elementType = arrayTy->getElementType();
733  Attribute previousElementAttr;
734  llvm::Constant *elementCst = nullptr;
736  constants.reserve(arrayTy->getNumElements());
737  for (Attribute elementAttr : arrayAttr) {
738  // Arrays with a single value or with repeating values are quite common.
739  // Short-circuit the translation when the element value is the same as
740  // the previous one.
741  if (!previousElementAttr || previousElementAttr != elementAttr) {
742  previousElementAttr = elementAttr;
743  elementCst =
744  getLLVMConstant(elementType, elementAttr, loc, moduleTranslation);
745  if (!elementCst)
746  return nullptr;
747  }
748  constants.push_back(elementCst);
749  }
750  return llvm::ConstantArray::get(arrayTy, constants);
751  }
752  }
753 
754  emitError(loc, "unsupported constant value");
755  return nullptr;
756 }
757 
758 ModuleTranslation::ModuleTranslation(Operation *module,
759  std::unique_ptr<llvm::Module> llvmModule)
760  : mlirModule(module), llvmModule(std::move(llvmModule)),
761  debugTranslation(
762  std::make_unique<DebugTranslation>(module, *this->llvmModule)),
763  loopAnnotationTranslation(std::make_unique<LoopAnnotationTranslation>(
764  *this, *this->llvmModule)),
765  typeTranslator(this->llvmModule->getContext()),
766  iface(module->getContext()) {
767  assert(satisfiesLLVMModule(mlirModule) &&
768  "mlirModule should honor LLVM's module semantics.");
769 }
770 
771 ModuleTranslation::~ModuleTranslation() {
772  if (ompBuilder && !ompBuilder->isFinalized())
773  ompBuilder->finalize();
774 }
775 
777  SmallVector<Region *> toProcess;
778  toProcess.push_back(&region);
779  while (!toProcess.empty()) {
780  Region *current = toProcess.pop_back_val();
781  for (Block &block : *current) {
782  blockMapping.erase(&block);
783  for (Value arg : block.getArguments())
784  valueMapping.erase(arg);
785  for (Operation &op : block) {
786  for (Value value : op.getResults())
787  valueMapping.erase(value);
788  if (op.hasSuccessors())
789  branchMapping.erase(&op);
790  if (isa<LLVM::GlobalOp>(op))
791  globalsMapping.erase(&op);
792  if (isa<LLVM::AliasOp>(op))
793  aliasesMapping.erase(&op);
794  if (isa<LLVM::IFuncOp>(op))
795  ifuncMapping.erase(&op);
796  if (isa<LLVM::CallOp>(op))
797  callMapping.erase(&op);
798  llvm::append_range(
799  toProcess,
800  llvm::map_range(op.getRegions(), [](Region &r) { return &r; }));
801  }
802  }
803  }
804 }
805 
806 /// Get the SSA value passed to the current block from the terminator operation
807 /// of its predecessor.
808 static Value getPHISourceValue(Block *current, Block *pred,
809  unsigned numArguments, unsigned index) {
810  Operation &terminator = *pred->getTerminator();
811  if (isa<LLVM::BrOp>(terminator))
812  return terminator.getOperand(index);
813 
814 #ifndef NDEBUG
815  llvm::SmallPtrSet<Block *, 4> seenSuccessors;
816  for (unsigned i = 0, e = terminator.getNumSuccessors(); i < e; ++i) {
817  Block *successor = terminator.getSuccessor(i);
818  auto branch = cast<BranchOpInterface>(terminator);
819  SuccessorOperands successorOperands = branch.getSuccessorOperands(i);
820  assert(
821  (!seenSuccessors.contains(successor) || successorOperands.empty()) &&
822  "successors with arguments in LLVM branches must be different blocks");
823  seenSuccessors.insert(successor);
824  }
825 #endif
826 
827  // For instructions that branch based on a condition value, we need to take
828  // the operands for the branch that was taken.
829  if (auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
830  // For conditional branches, we take the operands from either the "true" or
831  // the "false" branch.
832  return condBranchOp.getSuccessor(0) == current
833  ? condBranchOp.getTrueDestOperands()[index]
834  : condBranchOp.getFalseDestOperands()[index];
835  }
836 
837  if (auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
838  // For switches, we take the operands from either the default case, or from
839  // the case branch that was taken.
840  if (switchOp.getDefaultDestination() == current)
841  return switchOp.getDefaultOperands()[index];
842  for (const auto &i : llvm::enumerate(switchOp.getCaseDestinations()))
843  if (i.value() == current)
844  return switchOp.getCaseOperands(i.index())[index];
845  }
846 
847  if (auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(terminator)) {
848  // For indirect branches we take operands for each successor.
849  for (const auto &i : llvm::enumerate(indBrOp->getSuccessors())) {
850  if (indBrOp->getSuccessor(i.index()) == current)
851  return indBrOp.getSuccessorOperands(i.index())[index];
852  }
853  }
854 
855  if (auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
856  return invokeOp.getNormalDest() == current
857  ? invokeOp.getNormalDestOperands()[index]
858  : invokeOp.getUnwindDestOperands()[index];
859  }
860 
861  llvm_unreachable(
862  "only branch, switch or invoke operations can be terminators "
863  "of a block that has successors");
864 }
865 
866 /// Connect the PHI nodes to the results of preceding blocks.
868  const ModuleTranslation &state) {
869  // Skip the first block, it cannot be branched to and its arguments correspond
870  // to the arguments of the LLVM function.
871  for (Block &bb : llvm::drop_begin(region)) {
872  llvm::BasicBlock *llvmBB = state.lookupBlock(&bb);
873  auto phis = llvmBB->phis();
874  auto numArguments = bb.getNumArguments();
875  assert(numArguments == std::distance(phis.begin(), phis.end()));
876  for (auto [index, phiNode] : llvm::enumerate(phis)) {
877  for (auto *pred : bb.getPredecessors()) {
878  // Find the LLVM IR block that contains the converted terminator
879  // instruction and use it in the PHI node. Note that this block is not
880  // necessarily the same as state.lookupBlock(pred), some operations
881  // (in particular, OpenMP operations using OpenMPIRBuilder) may have
882  // split the blocks.
883  llvm::Instruction *terminator =
884  state.lookupBranch(pred->getTerminator());
885  assert(terminator && "missing the mapping for a terminator");
886  phiNode.addIncoming(state.lookupValue(getPHISourceValue(
887  &bb, pred, numArguments, index)),
888  terminator->getParent());
889  }
890  }
891  }
892 }
893 
895  llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic,
897  llvm::Module *module = builder.GetInsertBlock()->getModule();
898  llvm::Function *fn =
899  llvm::Intrinsic::getOrInsertDeclaration(module, intrinsic, tys);
900  return builder.CreateCall(fn, args);
901 }
902 
904  llvm::IRBuilderBase &builder, ModuleTranslation &moduleTranslation,
905  Operation *intrOp, llvm::Intrinsic::ID intrinsic, unsigned numResults,
906  ArrayRef<unsigned> overloadedResults, ArrayRef<unsigned> overloadedOperands,
907  ArrayRef<unsigned> immArgPositions,
908  ArrayRef<StringLiteral> immArgAttrNames) {
909  assert(immArgPositions.size() == immArgAttrNames.size() &&
910  "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
911  "length");
912 
914  size_t numOpBundleOperands = 0;
915  auto opBundleSizesAttr = cast_if_present<DenseI32ArrayAttr>(
916  intrOp->getAttr(LLVMDialect::getOpBundleSizesAttrName()));
917  auto opBundleTagsAttr = cast_if_present<ArrayAttr>(
918  intrOp->getAttr(LLVMDialect::getOpBundleTagsAttrName()));
919 
920  if (opBundleSizesAttr && opBundleTagsAttr) {
921  ArrayRef<int> opBundleSizes = opBundleSizesAttr.asArrayRef();
922  assert(opBundleSizes.size() == opBundleTagsAttr.size() &&
923  "operand bundles and tags do not match");
924 
925  numOpBundleOperands =
926  std::accumulate(opBundleSizes.begin(), opBundleSizes.end(), size_t(0));
927  assert(numOpBundleOperands <= intrOp->getNumOperands() &&
928  "operand bundle operands is more than the number of operands");
929 
930  ValueRange operands = intrOp->getOperands().take_back(numOpBundleOperands);
931  size_t nextOperandIdx = 0;
932  opBundles.reserve(opBundleSizesAttr.size());
933 
934  for (auto [opBundleTagAttr, bundleSize] :
935  llvm::zip(opBundleTagsAttr, opBundleSizes)) {
936  auto bundleTag = cast<StringAttr>(opBundleTagAttr).str();
937  auto bundleOperands = moduleTranslation.lookupValues(
938  operands.slice(nextOperandIdx, bundleSize));
939  opBundles.emplace_back(std::move(bundleTag), std::move(bundleOperands));
940  nextOperandIdx += bundleSize;
941  }
942  }
943 
944  // Map operands and attributes to LLVM values.
945  auto opOperands = intrOp->getOperands().drop_back(numOpBundleOperands);
946  auto operands = moduleTranslation.lookupValues(opOperands);
947  SmallVector<llvm::Value *> args(immArgPositions.size() + operands.size());
948  for (auto [immArgPos, immArgName] :
949  llvm::zip(immArgPositions, immArgAttrNames)) {
950  auto attr = llvm::cast<TypedAttr>(intrOp->getAttr(immArgName));
951  assert(attr.getType().isIntOrFloat() && "expected int or float immarg");
952  auto *type = moduleTranslation.convertType(attr.getType());
953  args[immArgPos] = LLVM::detail::getLLVMConstant(
954  type, attr, intrOp->getLoc(), moduleTranslation);
955  }
956  unsigned opArg = 0;
957  for (auto &arg : args) {
958  if (!arg)
959  arg = operands[opArg++];
960  }
961 
962  // Resolve overloaded intrinsic declaration.
963  SmallVector<llvm::Type *> overloadedTypes;
964  for (unsigned overloadedResultIdx : overloadedResults) {
965  if (numResults > 1) {
966  // More than one result is mapped to an LLVM struct.
967  overloadedTypes.push_back(moduleTranslation.convertType(
968  llvm::cast<LLVM::LLVMStructType>(intrOp->getResult(0).getType())
969  .getBody()[overloadedResultIdx]));
970  } else {
971  overloadedTypes.push_back(
972  moduleTranslation.convertType(intrOp->getResult(0).getType()));
973  }
974  }
975  for (unsigned overloadedOperandIdx : overloadedOperands)
976  overloadedTypes.push_back(args[overloadedOperandIdx]->getType());
977  llvm::Module *module = builder.GetInsertBlock()->getModule();
978  llvm::Function *llvmIntr = llvm::Intrinsic::getOrInsertDeclaration(
979  module, intrinsic, overloadedTypes);
980 
981  return builder.CreateCall(llvmIntr, args, opBundles);
982 }
983 
984 /// Given a single MLIR operation, create the corresponding LLVM IR operation
985 /// using the `builder`.
986 LogicalResult ModuleTranslation::convertOperation(Operation &op,
987  llvm::IRBuilderBase &builder,
988  bool recordInsertions) {
989  const LLVMTranslationDialectInterface *opIface = iface.getInterfaceFor(&op);
990  if (!opIface)
991  return op.emitError("cannot be converted to LLVM IR: missing "
992  "`LLVMTranslationDialectInterface` registration for "
993  "dialect for op: ")
994  << op.getName();
995 
996  InstructionCapturingInserter::CollectionScope scope(builder,
997  recordInsertions);
998  if (failed(opIface->convertOperation(&op, builder, *this)))
999  return op.emitError("LLVM Translation failed for operation: ")
1000  << op.getName();
1001 
1002  return convertDialectAttributes(&op, scope.getCapturedInstructions());
1003 }
1004 
1005 /// Convert block to LLVM IR. Unless `ignoreArguments` is set, emit PHI nodes
1006 /// to define values corresponding to the MLIR block arguments. These nodes
1007 /// are not connected to the source basic blocks, which may not exist yet. Uses
1008 /// `builder` to construct the LLVM IR. Expects the LLVM IR basic block to have
1009 /// been created for `bb` and included in the block mapping. Inserts new
1010 /// instructions at the end of the block and leaves `builder` in a state
1011 /// suitable for further insertion into the end of the block.
1012 LogicalResult ModuleTranslation::convertBlockImpl(Block &bb,
1013  bool ignoreArguments,
1014  llvm::IRBuilderBase &builder,
1015  bool recordInsertions) {
1016  builder.SetInsertPoint(lookupBlock(&bb));
1017  auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
1018 
1019  // Before traversing operations, make block arguments available through
1020  // value remapping and PHI nodes, but do not add incoming edges for the PHI
1021  // nodes just yet: those values may be defined by this or following blocks.
1022  // This step is omitted if "ignoreArguments" is set. The arguments of the
1023  // first block have been already made available through the remapping of
1024  // LLVM function arguments.
1025  if (!ignoreArguments) {
1026  auto predecessors = bb.getPredecessors();
1027  unsigned numPredecessors =
1028  std::distance(predecessors.begin(), predecessors.end());
1029  for (auto arg : bb.getArguments()) {
1030  auto wrappedType = arg.getType();
1031  if (!isCompatibleType(wrappedType))
1032  return emitError(bb.front().getLoc(),
1033  "block argument does not have an LLVM type");
1034  builder.SetCurrentDebugLocation(
1035  debugTranslation->translateLoc(arg.getLoc(), subprogram));
1036  llvm::Type *type = convertType(wrappedType);
1037  llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
1038  mapValue(arg, phi);
1039  }
1040  }
1041 
1042  // Traverse operations.
1043  for (auto &op : bb) {
1044  // Set the current debug location within the builder.
1045  builder.SetCurrentDebugLocation(
1046  debugTranslation->translateLoc(op.getLoc(), subprogram));
1047 
1048  if (failed(convertOperation(op, builder, recordInsertions)))
1049  return failure();
1050 
1051  // Set the branch weight metadata on the translated instruction.
1052  if (auto iface = dyn_cast<WeightedBranchOpInterface>(op))
1053  setBranchWeightsMetadata(iface);
1054  }
1055 
1056  return success();
1057 }
1058 
1059 /// A helper method to get the single Block in an operation honoring LLVM's
1060 /// module requirements.
1061 static Block &getModuleBody(Operation *module) {
1062  return module->getRegion(0).front();
1063 }
1064 
1065 /// A helper method to decide if a constant must not be set as a global variable
1066 /// initializer. For an external linkage variable, the variable with an
1067 /// initializer is considered externally visible and defined in this module, the
1068 /// variable without an initializer is externally available and is defined
1069 /// elsewhere.
1070 static bool shouldDropGlobalInitializer(llvm::GlobalValue::LinkageTypes linkage,
1071  llvm::Constant *cst) {
1072  return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
1073  linkage == llvm::GlobalVariable::ExternalWeakLinkage;
1074 }
1075 
1076 /// Sets the runtime preemption specifier of `gv` to dso_local if
1077 /// `dsoLocalRequested` is true, otherwise it is left unchanged.
1078 static void addRuntimePreemptionSpecifier(bool dsoLocalRequested,
1079  llvm::GlobalValue *gv) {
1080  if (dsoLocalRequested)
1081  gv->setDSOLocal(true);
1082 }
1083 
1084 /// Attempts to translate an MLIR attribute identified by `key`, optionally with
1085 /// the given `value`, into an LLVM IR attribute. Reports errors at `loc` if
1086 /// any. If the attribute name corresponds to a known LLVM IR attribute kind,
1087 /// creates the LLVM attribute of that kind; otherwise, keeps it as a string
1088 /// attribute. Performs additional checks for attributes known to have or not
1089 /// have a value in order to avoid assertions inside LLVM upon construction.
1090 static FailureOr<llvm::Attribute>
1091 convertMLIRAttributeToLLVM(Location loc, llvm::LLVMContext &ctx, StringRef key,
1092  StringRef value = StringRef()) {
1093  auto kind = llvm::Attribute::getAttrKindFromName(key);
1094  if (kind == llvm::Attribute::None)
1095  return llvm::Attribute::get(ctx, key, value);
1096 
1097  if (llvm::Attribute::isIntAttrKind(kind)) {
1098  if (value.empty())
1099  return emitError(loc) << "LLVM attribute '" << key << "' expects a value";
1100 
1101  int64_t result;
1102  if (!value.getAsInteger(/*Radix=*/0, result))
1103  return llvm::Attribute::get(ctx, kind, result);
1104  return llvm::Attribute::get(ctx, key, value);
1105  }
1106 
1107  if (!value.empty())
1108  return emitError(loc) << "LLVM attribute '" << key
1109  << "' does not expect a value, found '" << value
1110  << "'";
1111 
1112  return llvm::Attribute::get(ctx, kind);
1113 }
1114 
1115 /// Converts the MLIR attributes listed in the given array attribute into LLVM
1116 /// attributes. Returns an `AttrBuilder` containing the converted attributes.
1117 /// Reports error to `loc` if any and returns immediately. Expects `arrayAttr`
1118 /// to contain either string attributes, treated as value-less LLVM attributes,
1119 /// or array attributes containing two string attributes, with the first string
1120 /// being the name of the corresponding LLVM attribute and the second string
1121 /// beings its value. Note that even integer attributes are expected to have
1122 /// their values expressed as strings.
1123 static FailureOr<llvm::AttrBuilder>
1124 convertMLIRAttributesToLLVM(Location loc, llvm::LLVMContext &ctx,
1125  ArrayAttr arrayAttr, StringRef arrayAttrName) {
1126  llvm::AttrBuilder attrBuilder(ctx);
1127  if (!arrayAttr)
1128  return attrBuilder;
1129 
1130  for (Attribute attr : arrayAttr) {
1131  if (auto stringAttr = dyn_cast<StringAttr>(attr)) {
1132  FailureOr<llvm::Attribute> llvmAttr =
1133  convertMLIRAttributeToLLVM(loc, ctx, stringAttr.getValue());
1134  if (failed(llvmAttr))
1135  return failure();
1136  attrBuilder.addAttribute(*llvmAttr);
1137  continue;
1138  }
1139 
1140  auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1141  if (!arrayAttr || arrayAttr.size() != 2)
1142  return emitError(loc) << "expected '" << arrayAttrName
1143  << "' to contain string or array attributes";
1144 
1145  auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1146  auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1147  if (!keyAttr || !valueAttr)
1148  return emitError(loc) << "expected arrays within '" << arrayAttrName
1149  << "' to contain two strings";
1150 
1151  FailureOr<llvm::Attribute> llvmAttr = convertMLIRAttributeToLLVM(
1152  loc, ctx, keyAttr.getValue(), valueAttr.getValue());
1153  if (failed(llvmAttr))
1154  return failure();
1155  attrBuilder.addAttribute(*llvmAttr);
1156  }
1157 
1158  return attrBuilder;
1159 }
1160 
1161 LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
1162  // Mapping from compile unit to its respective set of global variables.
1164 
1165  // First, create all global variables and global aliases in LLVM IR. A global
1166  // or alias body may refer to another global/alias or itself, so all the
1167  // mapping needs to happen prior to body conversion.
1168 
1169  // Create all llvm::GlobalVariable
1170  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1171  llvm::Type *type = convertType(op.getType());
1172  llvm::Constant *cst = nullptr;
1173  if (op.getValueOrNull()) {
1174  // String attributes are treated separately because they cannot appear as
1175  // in-function constants and are thus not supported by getLLVMConstant.
1176  if (auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1177  cst = llvm::ConstantDataArray::getString(
1178  llvmModule->getContext(), strAttr.getValue(), /*AddNull=*/false);
1179  type = cst->getType();
1180  } else if (!(cst = getLLVMConstant(type, op.getValueOrNull(), op.getLoc(),
1181  *this))) {
1182  return failure();
1183  }
1184  }
1185 
1186  auto linkage = convertLinkageToLLVM(op.getLinkage());
1187 
1188  // LLVM IR requires constant with linkage other than external or weak
1189  // external to have initializers. If MLIR does not provide an initializer,
1190  // default to undef.
1191  bool dropInitializer = shouldDropGlobalInitializer(linkage, cst);
1192  if (!dropInitializer && !cst)
1193  cst = llvm::UndefValue::get(type);
1194  else if (dropInitializer && cst)
1195  cst = nullptr;
1196 
1197  auto *var = new llvm::GlobalVariable(
1198  *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1199  /*InsertBefore=*/nullptr,
1200  op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1201  : llvm::GlobalValue::NotThreadLocal,
1202  op.getAddrSpace(), op.getExternallyInitialized());
1203 
1204  if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1205  auto selectorOp = cast<ComdatSelectorOp>(
1207  var->setComdat(comdatMapping.lookup(selectorOp));
1208  }
1209 
1210  if (op.getUnnamedAddr().has_value())
1211  var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1212 
1213  if (op.getSection().has_value())
1214  var->setSection(*op.getSection());
1215 
1216  addRuntimePreemptionSpecifier(op.getDsoLocal(), var);
1217 
1218  std::optional<uint64_t> alignment = op.getAlignment();
1219  if (alignment.has_value())
1220  var->setAlignment(llvm::MaybeAlign(alignment.value()));
1221 
1222  var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1223 
1224  globalsMapping.try_emplace(op, var);
1225 
1226  // Add debug information if present.
1227  if (op.getDbgExprs()) {
1228  for (auto exprAttr :
1229  op.getDbgExprs()->getAsRange<DIGlobalVariableExpressionAttr>()) {
1230  llvm::DIGlobalVariableExpression *diGlobalExpr =
1231  debugTranslation->translateGlobalVariableExpression(exprAttr);
1232  llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1233  var->addDebugInfo(diGlobalExpr);
1234 
1235  // There is no `globals` field in DICompileUnitAttr which can be
1236  // directly assigned to DICompileUnit. We have to build the list by
1237  // looking at the dbgExpr of all the GlobalOps. The scope of the
1238  // variable is used to get the DICompileUnit in which to add it. But
1239  // there are cases where the scope of a global does not directly point
1240  // to the DICompileUnit and we have to do a bit more work to get to
1241  // it. Some of those cases are:
1242  //
1243  // 1. For the languages that support modules, the scope hierarchy can
1244  // be variable -> DIModule -> DICompileUnit
1245  //
1246  // 2. For the Fortran common block variable, the scope hierarchy can
1247  // be variable -> DICommonBlock -> DISubprogram -> DICompileUnit
1248  //
1249  // 3. For entities like static local variables in C or variable with
1250  // SAVE attribute in Fortran, the scope hierarchy can be
1251  // variable -> DISubprogram -> DICompileUnit
1252  llvm::DIScope *scope = diGlobalVar->getScope();
1253  if (auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1254  scope = mod->getScope();
1255  else if (auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
1256  if (auto *sp =
1257  dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
1258  scope = sp->getUnit();
1259  } else if (auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
1260  scope = sp->getUnit();
1261 
1262  // Get the compile unit (scope) of the the global variable.
1263  if (llvm::DICompileUnit *compileUnit =
1264  dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1265  // Update the compile unit with this incoming global variable
1266  // expression during the finalizing step later.
1267  allGVars[compileUnit].push_back(diGlobalExpr);
1268  }
1269  }
1270  }
1271 
1272  // Forward the target-specific attributes to LLVM.
1273  FailureOr<llvm::AttrBuilder> convertedTargetSpecificAttrs =
1275  op.getTargetSpecificAttrsAttr(),
1276  op.getTargetSpecificAttrsAttrName());
1277  if (failed(convertedTargetSpecificAttrs))
1278  return failure();
1279  var->addAttributes(*convertedTargetSpecificAttrs);
1280  }
1281 
1282  // Create all llvm::GlobalAlias
1283  for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1284  llvm::Type *type = convertType(op.getType());
1285  llvm::Constant *cst = nullptr;
1286  llvm::GlobalValue::LinkageTypes linkage =
1287  convertLinkageToLLVM(op.getLinkage());
1288  llvm::Module &llvmMod = *llvmModule;
1289 
1290  // Note address space and aliasee info isn't set just yet.
1291  llvm::GlobalAlias *var = llvm::GlobalAlias::create(
1292  type, op.getAddrSpace(), linkage, op.getSymName(), /*placeholder*/ cst,
1293  &llvmMod);
1294 
1295  var->setThreadLocalMode(op.getThreadLocal_()
1296  ? llvm::GlobalAlias::GeneralDynamicTLSModel
1297  : llvm::GlobalAlias::NotThreadLocal);
1298 
1299  // Note there is no need to setup the comdat because GlobalAlias calls into
1300  // the aliasee comdat information automatically.
1301 
1302  if (op.getUnnamedAddr().has_value())
1303  var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1304 
1305  var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1306 
1307  aliasesMapping.try_emplace(op, var);
1308  }
1309 
1310  // Convert global variable bodies.
1311  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1312  if (Block *initializer = op.getInitializerBlock()) {
1313  llvm::IRBuilder<llvm::TargetFolder> builder(
1314  llvmModule->getContext(),
1315  llvm::TargetFolder(llvmModule->getDataLayout()));
1316 
1317  [[maybe_unused]] int numConstantsHit = 0;
1318  [[maybe_unused]] int numConstantsErased = 0;
1319  DenseMap<llvm::ConstantAggregate *, int> constantAggregateUseMap;
1320 
1321  for (auto &op : initializer->without_terminator()) {
1322  if (failed(convertOperation(op, builder)))
1323  return emitError(op.getLoc(), "fail to convert global initializer");
1324  auto *cst = dyn_cast<llvm::Constant>(lookupValue(op.getResult(0)));
1325  if (!cst)
1326  return emitError(op.getLoc(), "unemittable constant value");
1327 
1328  // When emitting an LLVM constant, a new constant is created and the old
1329  // constant may become dangling and take space. We should remove the
1330  // dangling constants to avoid memory explosion especially for constant
1331  // arrays whose number of elements is large.
1332  // Because multiple operations may refer to the same constant, we need
1333  // to count the number of uses of each constant array and remove it only
1334  // when the count becomes zero.
1335  if (auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1336  numConstantsHit++;
1337  Value result = op.getResult(0);
1338  int numUsers = std::distance(result.use_begin(), result.use_end());
1339  auto [iterator, inserted] =
1340  constantAggregateUseMap.try_emplace(agg, numUsers);
1341  if (!inserted) {
1342  // Key already exists, update the value
1343  iterator->second += numUsers;
1344  }
1345  }
1346  // Scan the operands of the operation to decrement the use count of
1347  // constants. Erase the constant if the use count becomes zero.
1348  for (Value v : op.getOperands()) {
1349  auto cst = dyn_cast<llvm::ConstantAggregate>(lookupValue(v));
1350  if (!cst)
1351  continue;
1352  auto iter = constantAggregateUseMap.find(cst);
1353  assert(iter != constantAggregateUseMap.end() && "constant not found");
1354  iter->second--;
1355  if (iter->second == 0) {
1356  // NOTE: cannot call removeDeadConstantUsers() here because it
1357  // may remove the constant which has uses not be converted yet.
1358  if (cst->user_empty()) {
1359  cst->destroyConstant();
1360  numConstantsErased++;
1361  }
1362  constantAggregateUseMap.erase(iter);
1363  }
1364  }
1365  }
1366 
1367  ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1368  llvm::Constant *cst =
1369  cast<llvm::Constant>(lookupValue(ret.getOperand(0)));
1370  auto *global = cast<llvm::GlobalVariable>(lookupGlobal(op));
1371  if (!shouldDropGlobalInitializer(global->getLinkage(), cst))
1372  global->setInitializer(cst);
1373 
1374  // Try to remove the dangling constants again after all operations are
1375  // converted.
1376  for (auto it : constantAggregateUseMap) {
1377  auto cst = it.first;
1378  cst->removeDeadConstantUsers();
1379  if (cst->user_empty()) {
1380  cst->destroyConstant();
1381  numConstantsErased++;
1382  }
1383  }
1384 
1385  LLVM_DEBUG(llvm::dbgs()
1386  << "Convert initializer for " << op.getName() << "\n";
1387  llvm::dbgs() << numConstantsHit << " new constants hit\n";
1388  llvm::dbgs()
1389  << numConstantsErased << " dangling constants erased\n";);
1390  }
1391  }
1392 
1393  // Convert llvm.mlir.global_ctors and dtors.
1394  for (Operation &op : getModuleBody(mlirModule)) {
1395  auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1396  auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1397  if (!ctorOp && !dtorOp)
1398  continue;
1399 
1400  // The empty / zero initialized version of llvm.global_(c|d)tors cannot be
1401  // handled by appendGlobalFn logic below, which just ignores empty (c|d)tor
1402  // lists. Make sure it gets emitted.
1403  if ((ctorOp && ctorOp.getCtors().empty()) ||
1404  (dtorOp && dtorOp.getDtors().empty())) {
1405  llvm::IRBuilder<llvm::TargetFolder> builder(
1406  llvmModule->getContext(),
1407  llvm::TargetFolder(llvmModule->getDataLayout()));
1408  llvm::Type *eltTy = llvm::StructType::get(
1409  builder.getInt32Ty(), builder.getPtrTy(), builder.getPtrTy());
1410  llvm::ArrayType *at = llvm::ArrayType::get(eltTy, 0);
1411  llvm::Constant *zeroInit = llvm::Constant::getNullValue(at);
1412  (void)new llvm::GlobalVariable(
1413  *llvmModule, zeroInit->getType(), false,
1414  llvm::GlobalValue::AppendingLinkage, zeroInit,
1415  ctorOp ? "llvm.global_ctors" : "llvm.global_dtors");
1416  } else {
1417  auto range = ctorOp
1418  ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1419  : llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1420  auto appendGlobalFn =
1421  ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1422  for (const auto &[sym, prio] : range) {
1423  llvm::Function *f =
1424  lookupFunction(cast<FlatSymbolRefAttr>(sym).getValue());
1425  appendGlobalFn(*llvmModule, f, cast<IntegerAttr>(prio).getInt(),
1426  /*Data=*/nullptr);
1427  }
1428  }
1429  }
1430 
1431  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1432  if (failed(convertDialectAttributes(op, {})))
1433  return failure();
1434 
1435  // Finally, update the compile units their respective sets of global variables
1436  // created earlier.
1437  for (const auto &[compileUnit, globals] : allGVars) {
1438  compileUnit->replaceGlobalVariables(
1439  llvm::MDTuple::get(getLLVMContext(), globals));
1440  }
1441 
1442  // Convert global alias bodies.
1443  for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1444  Block &initializer = op.getInitializerBlock();
1445  llvm::IRBuilder<llvm::TargetFolder> builder(
1446  llvmModule->getContext(),
1447  llvm::TargetFolder(llvmModule->getDataLayout()));
1448 
1449  for (mlir::Operation &op : initializer.without_terminator()) {
1450  if (failed(convertOperation(op, builder)))
1451  return emitError(op.getLoc(), "fail to convert alias initializer");
1452  if (!isa<llvm::Constant>(lookupValue(op.getResult(0))))
1453  return emitError(op.getLoc(), "unemittable constant value");
1454  }
1455 
1456  auto ret = cast<ReturnOp>(initializer.getTerminator());
1457  auto *cst = cast<llvm::Constant>(lookupValue(ret.getOperand(0)));
1458  assert(aliasesMapping.count(op));
1459  auto *alias = cast<llvm::GlobalAlias>(aliasesMapping[op]);
1460  alias->setAliasee(cst);
1461  }
1462 
1463  for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>())
1464  if (failed(convertDialectAttributes(op, {})))
1465  return failure();
1466 
1467  return success();
1468 }
1469 
1470 /// Return a representation of `value` as metadata.
1471 static llvm::Metadata *convertIntegerToMetadata(llvm::LLVMContext &context,
1472  const llvm::APInt &value) {
1473  llvm::Constant *constant = llvm::ConstantInt::get(context, value);
1474  return llvm::ConstantAsMetadata::get(constant);
1475 }
1476 
1477 /// Return a representation of `value` as an MDNode.
1478 static llvm::MDNode *convertIntegerToMDNode(llvm::LLVMContext &context,
1479  const llvm::APInt &value) {
1480  return llvm::MDNode::get(context, convertIntegerToMetadata(context, value));
1481 }
1482 
1483 /// Return an MDNode encoding `vec_type_hint` metadata.
1484 static llvm::MDNode *convertVecTypeHintToMDNode(llvm::LLVMContext &context,
1485  llvm::Type *type,
1486  bool isSigned) {
1487  llvm::Metadata *typeMD =
1489  llvm::Metadata *isSignedMD =
1490  convertIntegerToMetadata(context, llvm::APInt(32, isSigned ? 1 : 0));
1491  return llvm::MDNode::get(context, {typeMD, isSignedMD});
1492 }
1493 
1494 /// Return an MDNode with a tuple given by the values in `values`.
1495 static llvm::MDNode *convertIntegerArrayToMDNode(llvm::LLVMContext &context,
1496  ArrayRef<int32_t> values) {
1498  llvm::transform(
1499  values, std::back_inserter(mdValues), [&context](int32_t value) {
1500  return convertIntegerToMetadata(context, llvm::APInt(32, value));
1501  });
1502  return llvm::MDNode::get(context, mdValues);
1503 }
1504 
1505 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1506  // Clear the block, branch value mappings, they are only relevant within one
1507  // function.
1508  blockMapping.clear();
1509  valueMapping.clear();
1510  branchMapping.clear();
1511  llvm::Function *llvmFunc = lookupFunction(func.getName());
1512 
1513  // Add function arguments to the value remapping table.
1514  for (auto [mlirArg, llvmArg] :
1515  llvm::zip(func.getArguments(), llvmFunc->args()))
1516  mapValue(mlirArg, &llvmArg);
1517 
1518  // Check the personality and set it.
1519  if (func.getPersonality()) {
1520  llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1521  if (llvm::Constant *pfunc = getLLVMConstant(ty, func.getPersonalityAttr(),
1522  func.getLoc(), *this))
1523  llvmFunc->setPersonalityFn(pfunc);
1524  }
1525 
1526  if (std::optional<StringRef> section = func.getSection())
1527  llvmFunc->setSection(*section);
1528 
1529  if (func.getArmStreaming())
1530  llvmFunc->addFnAttr("aarch64_pstate_sm_enabled");
1531  else if (func.getArmLocallyStreaming())
1532  llvmFunc->addFnAttr("aarch64_pstate_sm_body");
1533  else if (func.getArmStreamingCompatible())
1534  llvmFunc->addFnAttr("aarch64_pstate_sm_compatible");
1535 
1536  if (func.getArmNewZa())
1537  llvmFunc->addFnAttr("aarch64_new_za");
1538  else if (func.getArmInZa())
1539  llvmFunc->addFnAttr("aarch64_in_za");
1540  else if (func.getArmOutZa())
1541  llvmFunc->addFnAttr("aarch64_out_za");
1542  else if (func.getArmInoutZa())
1543  llvmFunc->addFnAttr("aarch64_inout_za");
1544  else if (func.getArmPreservesZa())
1545  llvmFunc->addFnAttr("aarch64_preserves_za");
1546 
1547  if (auto targetCpu = func.getTargetCpu())
1548  llvmFunc->addFnAttr("target-cpu", *targetCpu);
1549 
1550  if (auto tuneCpu = func.getTuneCpu())
1551  llvmFunc->addFnAttr("tune-cpu", *tuneCpu);
1552 
1553  if (auto reciprocalEstimates = func.getReciprocalEstimates())
1554  llvmFunc->addFnAttr("reciprocal-estimates", *reciprocalEstimates);
1555 
1556  if (auto preferVectorWidth = func.getPreferVectorWidth())
1557  llvmFunc->addFnAttr("prefer-vector-width", *preferVectorWidth);
1558 
1559  if (auto attr = func.getVscaleRange())
1560  llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1561  getLLVMContext(), attr->getMinRange().getInt(),
1562  attr->getMaxRange().getInt()));
1563 
1564  if (auto unsafeFpMath = func.getUnsafeFpMath())
1565  llvmFunc->addFnAttr("unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1566 
1567  if (auto noInfsFpMath = func.getNoInfsFpMath())
1568  llvmFunc->addFnAttr("no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1569 
1570  if (auto noNansFpMath = func.getNoNansFpMath())
1571  llvmFunc->addFnAttr("no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1572 
1573  if (auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1574  llvmFunc->addFnAttr("no-signed-zeros-fp-math",
1575  llvm::toStringRef(*noSignedZerosFpMath));
1576 
1577  if (auto denormalFpMath = func.getDenormalFpMath())
1578  llvmFunc->addFnAttr("denormal-fp-math", *denormalFpMath);
1579 
1580  if (auto denormalFpMathF32 = func.getDenormalFpMathF32())
1581  llvmFunc->addFnAttr("denormal-fp-math-f32", *denormalFpMathF32);
1582 
1583  if (auto fpContract = func.getFpContract())
1584  llvmFunc->addFnAttr("fp-contract", *fpContract);
1585 
1586  if (auto instrumentFunctionEntry = func.getInstrumentFunctionEntry())
1587  llvmFunc->addFnAttr("instrument-function-entry", *instrumentFunctionEntry);
1588 
1589  if (auto instrumentFunctionExit = func.getInstrumentFunctionExit())
1590  llvmFunc->addFnAttr("instrument-function-exit", *instrumentFunctionExit);
1591 
1592  // First, create all blocks so we can jump to them.
1593  llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1594  for (auto &bb : func) {
1595  auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1596  llvmBB->insertInto(llvmFunc);
1597  mapBlock(&bb, llvmBB);
1598  }
1599 
1600  // Then, convert blocks one by one in topological order to ensure defs are
1601  // converted before uses.
1602  auto blocks = getBlocksSortedByDominance(func.getBody());
1603  for (Block *bb : blocks) {
1604  CapturingIRBuilder builder(llvmContext,
1605  llvm::TargetFolder(llvmModule->getDataLayout()));
1606  if (failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1607  /*recordInsertions=*/true)))
1608  return failure();
1609  }
1610 
1611  // After all blocks have been traversed and values mapped, connect the PHI
1612  // nodes to the results of preceding blocks.
1613  detail::connectPHINodes(func.getBody(), *this);
1614 
1615  // Finally, convert dialect attributes attached to the function.
1616  return convertDialectAttributes(func, {});
1617 }
1618 
1619 LogicalResult ModuleTranslation::convertDialectAttributes(
1620  Operation *op, ArrayRef<llvm::Instruction *> instructions) {
1621  for (NamedAttribute attribute : op->getDialectAttrs())
1622  if (failed(iface.amendOperation(op, instructions, attribute, *this)))
1623  return failure();
1624  return success();
1625 }
1626 
1627 /// Converts memory effect attributes from `func` and attaches them to
1628 /// `llvmFunc`.
1629 static void convertFunctionMemoryAttributes(LLVMFuncOp func,
1630  llvm::Function *llvmFunc) {
1631  if (!func.getMemoryEffects())
1632  return;
1633 
1634  MemoryEffectsAttr memEffects = func.getMemoryEffectsAttr();
1635 
1636  // Add memory effects incrementally.
1637  llvm::MemoryEffects newMemEffects =
1638  llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1639  convertModRefInfoToLLVM(memEffects.getArgMem()));
1640  newMemEffects |= llvm::MemoryEffects(
1641  llvm::MemoryEffects::Location::InaccessibleMem,
1642  convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1643  newMemEffects |=
1644  llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1645  convertModRefInfoToLLVM(memEffects.getOther()));
1646  llvmFunc->setMemoryEffects(newMemEffects);
1647 }
1648 
1649 /// Converts function attributes from `func` and attaches them to `llvmFunc`.
1650 static void convertFunctionAttributes(LLVMFuncOp func,
1651  llvm::Function *llvmFunc) {
1652  if (func.getNoInlineAttr())
1653  llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1654  if (func.getAlwaysInlineAttr())
1655  llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1656  if (func.getOptimizeNoneAttr())
1657  llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1658  if (func.getConvergentAttr())
1659  llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1660  if (func.getNoUnwindAttr())
1661  llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1662  if (func.getWillReturnAttr())
1663  llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1664  if (TargetFeaturesAttr targetFeatAttr = func.getTargetFeaturesAttr())
1665  llvmFunc->addFnAttr("target-features", targetFeatAttr.getFeaturesString());
1666  if (FramePointerKindAttr fpAttr = func.getFramePointerAttr())
1667  llvmFunc->addFnAttr("frame-pointer", stringifyFramePointerKind(
1668  fpAttr.getFramePointerKind()));
1669  if (UWTableKindAttr uwTableKindAttr = func.getUwtableKindAttr())
1670  llvmFunc->setUWTableKind(
1671  convertUWTableKindToLLVM(uwTableKindAttr.getUwtableKind()));
1672  convertFunctionMemoryAttributes(func, llvmFunc);
1673 }
1674 
1675 /// Converts function attributes from `func` and attaches them to `llvmFunc`.
1676 static void convertFunctionKernelAttributes(LLVMFuncOp func,
1677  llvm::Function *llvmFunc,
1678  ModuleTranslation &translation) {
1679  llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1680 
1681  if (VecTypeHintAttr vecTypeHint = func.getVecTypeHintAttr()) {
1682  Type type = vecTypeHint.getHint().getValue();
1683  llvm::Type *llvmType = translation.convertType(type);
1684  bool isSigned = vecTypeHint.getIsSigned();
1685  llvmFunc->setMetadata(
1686  func.getVecTypeHintAttrName(),
1687  convertVecTypeHintToMDNode(llvmContext, llvmType, isSigned));
1688  }
1689 
1690  if (std::optional<ArrayRef<int32_t>> workGroupSizeHint =
1691  func.getWorkGroupSizeHint()) {
1692  llvmFunc->setMetadata(
1693  func.getWorkGroupSizeHintAttrName(),
1694  convertIntegerArrayToMDNode(llvmContext, *workGroupSizeHint));
1695  }
1696 
1697  if (std::optional<ArrayRef<int32_t>> reqdWorkGroupSize =
1698  func.getReqdWorkGroupSize()) {
1699  llvmFunc->setMetadata(
1700  func.getReqdWorkGroupSizeAttrName(),
1701  convertIntegerArrayToMDNode(llvmContext, *reqdWorkGroupSize));
1702  }
1703 
1704  if (std::optional<uint32_t> intelReqdSubGroupSize =
1705  func.getIntelReqdSubGroupSize()) {
1706  llvmFunc->setMetadata(
1707  func.getIntelReqdSubGroupSizeAttrName(),
1708  convertIntegerToMDNode(llvmContext,
1709  llvm::APInt(32, *intelReqdSubGroupSize)));
1710  }
1711 }
1712 
1713 static LogicalResult convertParameterAttr(llvm::AttrBuilder &attrBuilder,
1714  llvm::Attribute::AttrKind llvmKind,
1715  NamedAttribute namedAttr,
1716  ModuleTranslation &moduleTranslation,
1717  Location loc) {
1719  .Case<TypeAttr>([&](auto typeAttr) {
1720  attrBuilder.addTypeAttr(
1721  llvmKind, moduleTranslation.convertType(typeAttr.getValue()));
1722  return success();
1723  })
1724  .Case<IntegerAttr>([&](auto intAttr) {
1725  attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1726  return success();
1727  })
1728  .Case<UnitAttr>([&](auto) {
1729  attrBuilder.addAttribute(llvmKind);
1730  return success();
1731  })
1732  .Case<LLVM::ConstantRangeAttr>([&](auto rangeAttr) {
1733  attrBuilder.addConstantRangeAttr(
1734  llvmKind,
1735  llvm::ConstantRange(rangeAttr.getLower(), rangeAttr.getUpper()));
1736  return success();
1737  })
1738  .Default([loc](auto) {
1739  return emitError(loc, "unsupported parameter attribute type");
1740  });
1741 }
1742 
1743 FailureOr<llvm::AttrBuilder>
1744 ModuleTranslation::convertParameterAttrs(LLVMFuncOp func, int argIdx,
1745  DictionaryAttr paramAttrs) {
1746  llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1747  auto attrNameToKindMapping = getAttrNameToKindMapping();
1748  Location loc = func.getLoc();
1749 
1750  for (auto namedAttr : paramAttrs) {
1751  auto it = attrNameToKindMapping.find(namedAttr.getName());
1752  if (it != attrNameToKindMapping.end()) {
1753  llvm::Attribute::AttrKind llvmKind = it->second;
1754  if (failed(convertParameterAttr(attrBuilder, llvmKind, namedAttr, *this,
1755  loc)))
1756  return failure();
1757  } else if (namedAttr.getNameDialect()) {
1758  if (failed(iface.convertParameterAttr(func, argIdx, namedAttr, *this)))
1759  return failure();
1760  }
1761  }
1762 
1763  return attrBuilder;
1764 }
1765 
1767  ArgAndResultAttrsOpInterface attrsOp, llvm::CallBase *call,
1768  ArrayRef<unsigned> immArgPositions) {
1769  // Convert the argument attributes.
1770  if (ArrayAttr argAttrsArray = attrsOp.getArgAttrsAttr()) {
1771  unsigned argAttrIdx = 0;
1772  llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
1773  immArgPositions.end());
1774  for (unsigned argIdx : llvm::seq<unsigned>(call->arg_size())) {
1775  if (argAttrIdx >= argAttrsArray.size())
1776  break;
1777  // Skip immediate arguments (they have no entries in argAttrsArray).
1778  if (immArgPositionsSet.contains(argIdx))
1779  continue;
1780  // Skip empty argument attributes.
1781  auto argAttrs = cast<DictionaryAttr>(argAttrsArray[argAttrIdx++]);
1782  if (argAttrs.empty())
1783  continue;
1784  // Convert and add attributes to the call instruction.
1785  FailureOr<llvm::AttrBuilder> attrBuilder =
1786  convertParameterAttrs(attrsOp->getLoc(), argAttrs);
1787  if (failed(attrBuilder))
1788  return failure();
1789  call->addParamAttrs(argIdx, *attrBuilder);
1790  }
1791  }
1792 
1793  // Convert the result attributes.
1794  if (ArrayAttr resAttrsArray = attrsOp.getResAttrsAttr()) {
1795  if (!resAttrsArray.empty()) {
1796  auto resAttrs = cast<DictionaryAttr>(resAttrsArray[0]);
1797  FailureOr<llvm::AttrBuilder> attrBuilder =
1798  convertParameterAttrs(attrsOp->getLoc(), resAttrs);
1799  if (failed(attrBuilder))
1800  return failure();
1801  call->addRetAttrs(*attrBuilder);
1802  }
1803  }
1804 
1805  return success();
1806 }
1807 
1808 FailureOr<llvm::AttrBuilder>
1809 ModuleTranslation::convertParameterAttrs(Location loc,
1810  DictionaryAttr paramAttrs) {
1811  llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1812  auto attrNameToKindMapping = getAttrNameToKindMapping();
1813 
1814  for (auto namedAttr : paramAttrs) {
1815  auto it = attrNameToKindMapping.find(namedAttr.getName());
1816  if (it != attrNameToKindMapping.end()) {
1817  llvm::Attribute::AttrKind llvmKind = it->second;
1818  if (failed(convertParameterAttr(attrBuilder, llvmKind, namedAttr, *this,
1819  loc)))
1820  return failure();
1821  }
1822  }
1823 
1824  return attrBuilder;
1825 }
1826 
1827 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1828  // Declare all functions first because there may be function calls that form a
1829  // call graph with cycles, or global initializers that reference functions.
1830  for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1831  llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1832  function.getName(),
1833  cast<llvm::FunctionType>(convertType(function.getFunctionType())));
1834  llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1835  llvmFunc->setLinkage(convertLinkageToLLVM(function.getLinkage()));
1836  llvmFunc->setCallingConv(convertCConvToLLVM(function.getCConv()));
1837  mapFunction(function.getName(), llvmFunc);
1838  addRuntimePreemptionSpecifier(function.getDsoLocal(), llvmFunc);
1839 
1840  // Convert function attributes.
1841  convertFunctionAttributes(function, llvmFunc);
1842 
1843  // Convert function kernel attributes to metadata.
1844  convertFunctionKernelAttributes(function, llvmFunc, *this);
1845 
1846  // Convert function_entry_count attribute to metadata.
1847  if (std::optional<uint64_t> entryCount = function.getFunctionEntryCount())
1848  llvmFunc->setEntryCount(entryCount.value());
1849 
1850  // Convert result attributes.
1851  if (ArrayAttr allResultAttrs = function.getAllResultAttrs()) {
1852  DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1853  FailureOr<llvm::AttrBuilder> attrBuilder =
1854  convertParameterAttrs(function, -1, resultAttrs);
1855  if (failed(attrBuilder))
1856  return failure();
1857  llvmFunc->addRetAttrs(*attrBuilder);
1858  }
1859 
1860  // Convert argument attributes.
1861  for (auto [argIdx, llvmArg] : llvm::enumerate(llvmFunc->args())) {
1862  if (DictionaryAttr argAttrs = function.getArgAttrDict(argIdx)) {
1863  FailureOr<llvm::AttrBuilder> attrBuilder =
1864  convertParameterAttrs(function, argIdx, argAttrs);
1865  if (failed(attrBuilder))
1866  return failure();
1867  llvmArg.addAttrs(*attrBuilder);
1868  }
1869  }
1870 
1871  // Forward the pass-through attributes to LLVM.
1872  FailureOr<llvm::AttrBuilder> convertedPassthroughAttrs =
1873  convertMLIRAttributesToLLVM(function.getLoc(), llvmFunc->getContext(),
1874  function.getPassthroughAttr(),
1875  function.getPassthroughAttrName());
1876  if (failed(convertedPassthroughAttrs))
1877  return failure();
1878  llvmFunc->addFnAttrs(*convertedPassthroughAttrs);
1879 
1880  // Convert visibility attribute.
1881  llvmFunc->setVisibility(convertVisibilityToLLVM(function.getVisibility_()));
1882 
1883  // Convert the comdat attribute.
1884  if (std::optional<mlir::SymbolRefAttr> comdat = function.getComdat()) {
1885  auto selectorOp = cast<ComdatSelectorOp>(
1886  SymbolTable::lookupNearestSymbolFrom(function, *comdat));
1887  llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1888  }
1889 
1890  if (auto gc = function.getGarbageCollector())
1891  llvmFunc->setGC(gc->str());
1892 
1893  if (auto unnamedAddr = function.getUnnamedAddr())
1894  llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1895 
1896  if (auto alignment = function.getAlignment())
1897  llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1898 
1899  // Translate the debug information for this function.
1900  debugTranslation->translate(function, *llvmFunc);
1901  }
1902 
1903  return success();
1904 }
1905 
1906 LogicalResult ModuleTranslation::convertFunctions() {
1907  // Convert functions.
1908  for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1909  // Do not convert external functions, but do process dialect attributes
1910  // attached to them.
1911  if (function.isExternal()) {
1912  if (failed(convertDialectAttributes(function, {})))
1913  return failure();
1914  continue;
1915  }
1916 
1917  if (failed(convertOneFunction(function)))
1918  return failure();
1919  }
1920 
1921  return success();
1922 }
1923 
1924 LogicalResult ModuleTranslation::convertIFuncs() {
1925  for (auto op : getModuleBody(mlirModule).getOps<IFuncOp>()) {
1926  llvm::Type *type = convertType(op.getIFuncType());
1927  llvm::GlobalValue::LinkageTypes linkage =
1928  convertLinkageToLLVM(op.getLinkage());
1929  llvm::Constant *resolver;
1930  if (auto *resolverFn = lookupFunction(op.getResolver())) {
1931  resolver = cast<llvm::Constant>(resolverFn);
1932  } else {
1934  op.getResolverAttr());
1935  resolver = cast<llvm::Constant>(lookupAlias(aliasOp));
1936  }
1937 
1938  auto *ifunc =
1939  llvm::GlobalIFunc::create(type, op.getAddressSpace(), linkage,
1940  op.getSymName(), resolver, llvmModule.get());
1941  addRuntimePreemptionSpecifier(op.getDsoLocal(), ifunc);
1942  ifunc->setUnnamedAddr(convertUnnamedAddrToLLVM(op.getUnnamedAddr()));
1943  ifunc->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1944 
1945  ifuncMapping.try_emplace(op, ifunc);
1946  }
1947 
1948  return success();
1949 }
1950 
1951 LogicalResult ModuleTranslation::convertComdats() {
1952  for (auto comdatOp : getModuleBody(mlirModule).getOps<ComdatOp>()) {
1953  for (auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1954  llvm::Module *module = getLLVMModule();
1955  if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1956  return emitError(selectorOp.getLoc())
1957  << "comdat selection symbols must be unique even in different "
1958  "comdat regions";
1959  llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1960  comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1961  comdatMapping.try_emplace(selectorOp, comdat);
1962  }
1963  }
1964  return success();
1965 }
1966 
1967 LogicalResult ModuleTranslation::convertUnresolvedBlockAddress() {
1968  for (auto &[blockAddressOp, llvmCst] : unresolvedBlockAddressMapping) {
1969  BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
1970  llvm::BasicBlock *llvmBlock = lookupBlockAddress(blockAddressAttr);
1971  assert(llvmBlock && "expected LLVM blocks to be already translated");
1972 
1973  // Update mapping with new block address constant.
1974  auto *llvmBlockAddr = llvm::BlockAddress::get(
1975  lookupFunction(blockAddressAttr.getFunction().getValue()), llvmBlock);
1976  llvmCst->replaceAllUsesWith(llvmBlockAddr);
1977  assert(llvmCst->use_empty() && "expected all uses to be replaced");
1978  cast<llvm::GlobalVariable>(llvmCst)->eraseFromParent();
1979  }
1980  unresolvedBlockAddressMapping.clear();
1981  return success();
1982 }
1983 
1984 void ModuleTranslation::setAccessGroupsMetadata(AccessGroupOpInterface op,
1985  llvm::Instruction *inst) {
1986  if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1987  inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1988 }
1989 
1990 llvm::MDNode *
1991 ModuleTranslation::getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr) {
1992  auto [scopeIt, scopeInserted] =
1993  aliasScopeMetadataMapping.try_emplace(aliasScopeAttr, nullptr);
1994  if (!scopeInserted)
1995  return scopeIt->second;
1996  llvm::LLVMContext &ctx = llvmModule->getContext();
1997  auto dummy = llvm::MDNode::getTemporary(ctx, {});
1998  // Convert the domain metadata node if necessary.
1999  auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
2000  aliasScopeAttr.getDomain(), nullptr);
2001  if (insertedDomain) {
2003  // Placeholder for potential self-reference.
2004  operands.push_back(dummy.get());
2005  if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
2006  operands.push_back(llvm::MDString::get(ctx, description));
2007  domainIt->second = llvm::MDNode::get(ctx, operands);
2008  // Self-reference for uniqueness.
2009  llvm::Metadata *replacement;
2010  if (auto stringAttr =
2011  dyn_cast<StringAttr>(aliasScopeAttr.getDomain().getId()))
2012  replacement = llvm::MDString::get(ctx, stringAttr.getValue());
2013  else
2014  replacement = domainIt->second;
2015  domainIt->second->replaceOperandWith(0, replacement);
2016  }
2017  // Convert the scope metadata node.
2018  assert(domainIt->second && "Scope's domain should already be valid");
2020  // Placeholder for potential self-reference.
2021  operands.push_back(dummy.get());
2022  operands.push_back(domainIt->second);
2023  if (StringAttr description = aliasScopeAttr.getDescription())
2024  operands.push_back(llvm::MDString::get(ctx, description));
2025  scopeIt->second = llvm::MDNode::get(ctx, operands);
2026  // Self-reference for uniqueness.
2027  llvm::Metadata *replacement;
2028  if (auto stringAttr = dyn_cast<StringAttr>(aliasScopeAttr.getId()))
2029  replacement = llvm::MDString::get(ctx, stringAttr.getValue());
2030  else
2031  replacement = scopeIt->second;
2032  scopeIt->second->replaceOperandWith(0, replacement);
2033  return scopeIt->second;
2034 }
2035 
2037  ArrayRef<AliasScopeAttr> aliasScopeAttrs) {
2039  nodes.reserve(aliasScopeAttrs.size());
2040  for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
2041  nodes.push_back(getOrCreateAliasScope(aliasScopeAttr));
2042  return llvm::MDNode::get(getLLVMContext(), nodes);
2043 }
2044 
2045 void ModuleTranslation::setAliasScopeMetadata(AliasAnalysisOpInterface op,
2046  llvm::Instruction *inst) {
2047  auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs, unsigned kind) {
2048  if (!aliasScopeAttrs || aliasScopeAttrs.empty())
2049  return;
2050  llvm::MDNode *node = getOrCreateAliasScopes(
2051  llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
2052  inst->setMetadata(kind, node);
2053  };
2054 
2055  populateScopeMetadata(op.getAliasScopesOrNull(),
2056  llvm::LLVMContext::MD_alias_scope);
2057  populateScopeMetadata(op.getNoAliasScopesOrNull(),
2058  llvm::LLVMContext::MD_noalias);
2059 }
2060 
2061 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr) const {
2062  return tbaaMetadataMapping.lookup(tbaaAttr);
2063 }
2064 
2065 void ModuleTranslation::setTBAAMetadata(AliasAnalysisOpInterface op,
2066  llvm::Instruction *inst) {
2067  ArrayAttr tagRefs = op.getTBAATagsOrNull();
2068  if (!tagRefs || tagRefs.empty())
2069  return;
2070 
2071  // LLVM IR currently does not support attaching more than one TBAA access tag
2072  // to a memory accessing instruction. It may be useful to support this in
2073  // future, but for the time being just ignore the metadata if MLIR operation
2074  // has multiple access tags.
2075  if (tagRefs.size() > 1) {
2076  op.emitWarning() << "TBAA access tags were not translated, because LLVM "
2077  "IR only supports a single tag per instruction";
2078  return;
2079  }
2080 
2081  llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
2082  inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
2083 }
2084 
2086  DereferenceableOpInterface op, llvm::Instruction *inst) {
2087  DereferenceableAttr derefAttr = op.getDereferenceableOrNull();
2088  if (!derefAttr)
2089  return;
2090 
2091  llvm::MDNode *derefSizeNode = llvm::MDNode::get(
2092  getLLVMContext(),
2094  llvm::IntegerType::get(getLLVMContext(), 64), derefAttr.getBytes())));
2095  unsigned kindId = derefAttr.getMayBeNull()
2096  ? llvm::LLVMContext::MD_dereferenceable_or_null
2097  : llvm::LLVMContext::MD_dereferenceable;
2098  inst->setMetadata(kindId, derefSizeNode);
2099 }
2100 
2101 void ModuleTranslation::setBranchWeightsMetadata(WeightedBranchOpInterface op) {
2102  SmallVector<uint32_t> weights;
2103  llvm::transform(op.getWeights(), std::back_inserter(weights),
2104  [](int32_t value) { return static_cast<uint32_t>(value); });
2105  if (weights.empty())
2106  return;
2107 
2108  llvm::Instruction *inst = isa<CallOp>(op) ? lookupCall(op) : lookupBranch(op);
2109  assert(inst && "expected the operation to have a mapping to an instruction");
2110  inst->setMetadata(
2111  llvm::LLVMContext::MD_prof,
2112  llvm::MDBuilder(getLLVMContext()).createBranchWeights(weights));
2113 }
2114 
2115 LogicalResult ModuleTranslation::createTBAAMetadata() {
2116  llvm::LLVMContext &ctx = llvmModule->getContext();
2117  llvm::IntegerType *offsetTy = llvm::IntegerType::get(ctx, 64);
2118 
2119  // Walk the entire module and create all metadata nodes for the TBAA
2120  // attributes. The code below relies on two invariants of the
2121  // `AttrTypeWalker`:
2122  // 1. Attributes are visited in post-order: Since the attributes create a DAG,
2123  // this ensures that any lookups into `tbaaMetadataMapping` for child
2124  // attributes succeed.
2125  // 2. Attributes are only ever visited once: This way we don't leak any
2126  // LLVM metadata instances.
2127  AttrTypeWalker walker;
2128  walker.addWalk([&](TBAARootAttr root) {
2129  tbaaMetadataMapping.insert(
2130  {root, llvm::MDNode::get(ctx, llvm::MDString::get(ctx, root.getId()))});
2131  });
2132 
2133  walker.addWalk([&](TBAATypeDescriptorAttr descriptor) {
2135  operands.push_back(llvm::MDString::get(ctx, descriptor.getId()));
2136  for (TBAAMemberAttr member : descriptor.getMembers()) {
2137  operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
2138  operands.push_back(llvm::ConstantAsMetadata::get(
2139  llvm::ConstantInt::get(offsetTy, member.getOffset())));
2140  }
2141 
2142  tbaaMetadataMapping.insert({descriptor, llvm::MDNode::get(ctx, operands)});
2143  });
2144 
2145  walker.addWalk([&](TBAATagAttr tag) {
2147 
2148  operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
2149  operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
2150 
2151  operands.push_back(llvm::ConstantAsMetadata::get(
2152  llvm::ConstantInt::get(offsetTy, tag.getOffset())));
2153  if (tag.getConstant())
2154  operands.push_back(
2156 
2157  tbaaMetadataMapping.insert({tag, llvm::MDNode::get(ctx, operands)});
2158  });
2159 
2160  mlirModule->walk([&](AliasAnalysisOpInterface analysisOpInterface) {
2161  if (auto attr = analysisOpInterface.getTBAATagsOrNull())
2162  walker.walk(attr);
2163  });
2164 
2165  return success();
2166 }
2167 
2168 LogicalResult ModuleTranslation::createIdentMetadata() {
2169  if (auto attr = mlirModule->getAttrOfType<StringAttr>(
2170  LLVMDialect::getIdentAttrName())) {
2171  StringRef ident = attr;
2172  llvm::LLVMContext &ctx = llvmModule->getContext();
2173  llvm::NamedMDNode *namedMd =
2174  llvmModule->getOrInsertNamedMetadata(LLVMDialect::getIdentAttrName());
2175  llvm::MDNode *md = llvm::MDNode::get(ctx, llvm::MDString::get(ctx, ident));
2176  namedMd->addOperand(md);
2177  }
2178 
2179  return success();
2180 }
2181 
2182 LogicalResult ModuleTranslation::createCommandlineMetadata() {
2183  if (auto attr = mlirModule->getAttrOfType<StringAttr>(
2184  LLVMDialect::getCommandlineAttrName())) {
2185  StringRef cmdLine = attr;
2186  llvm::LLVMContext &ctx = llvmModule->getContext();
2187  llvm::NamedMDNode *nmd = llvmModule->getOrInsertNamedMetadata(
2188  LLVMDialect::getCommandlineAttrName());
2189  llvm::MDNode *md =
2190  llvm::MDNode::get(ctx, llvm::MDString::get(ctx, cmdLine));
2191  nmd->addOperand(md);
2192  }
2193 
2194  return success();
2195 }
2196 
2197 LogicalResult ModuleTranslation::createDependentLibrariesMetadata() {
2198  if (auto dependentLibrariesAttr = mlirModule->getDiscardableAttr(
2199  LLVM::LLVMDialect::getDependentLibrariesAttrName())) {
2200  auto *nmd =
2201  llvmModule->getOrInsertNamedMetadata("llvm.dependent-libraries");
2202  llvm::LLVMContext &ctx = llvmModule->getContext();
2203  for (auto libAttr :
2204  cast<ArrayAttr>(dependentLibrariesAttr).getAsRange<StringAttr>()) {
2205  auto *md =
2206  llvm::MDNode::get(ctx, llvm::MDString::get(ctx, libAttr.getValue()));
2207  nmd->addOperand(md);
2208  }
2209  }
2210  return success();
2211 }
2212 
2214  llvm::Instruction *inst) {
2215  LoopAnnotationAttr attr =
2217  .Case<LLVM::BrOp, LLVM::CondBrOp>(
2218  [](auto branchOp) { return branchOp.getLoopAnnotationAttr(); });
2219  if (!attr)
2220  return;
2221  llvm::MDNode *loopMD =
2222  loopAnnotationTranslation->translateLoopAnnotation(attr, op);
2223  inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
2224 }
2225 
2226 void ModuleTranslation::setDisjointFlag(Operation *op, llvm::Value *value) {
2227  auto iface = cast<DisjointFlagInterface>(op);
2228  // We do a dyn_cast here in case the value got folded into a constant.
2229  if (auto disjointInst = dyn_cast<llvm::PossiblyDisjointInst>(value))
2230  disjointInst->setIsDisjoint(iface.getIsDisjoint());
2231 }
2232 
2234  return typeTranslator.translateType(type);
2235 }
2236 
2237 /// A helper to look up remapped operands in the value remapping table.
2239  SmallVector<llvm::Value *> remapped;
2240  remapped.reserve(values.size());
2241  for (Value v : values)
2242  remapped.push_back(lookupValue(v));
2243  return remapped;
2244 }
2245 
2246 llvm::OpenMPIRBuilder *ModuleTranslation::getOpenMPBuilder() {
2247  if (!ompBuilder) {
2248  ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
2249  ompBuilder->initialize();
2250 
2251  // Flags represented as top-level OpenMP dialect attributes are set in
2252  // `OpenMPDialectLLVMIRTranslationInterface::amendOperation()`. Here we set
2253  // the default configuration.
2254  ompBuilder->setConfig(llvm::OpenMPIRBuilderConfig(
2255  /* IsTargetDevice = */ false, /* IsGPU = */ false,
2256  /* OpenMPOffloadMandatory = */ false,
2257  /* HasRequiresReverseOffload = */ false,
2258  /* HasRequiresUnifiedAddress = */ false,
2259  /* HasRequiresUnifiedSharedMemory = */ false,
2260  /* HasRequiresDynamicAllocators = */ false));
2261  }
2262  return ompBuilder.get();
2263 }
2264 
2266  llvm::DILocalScope *scope) {
2267  return debugTranslation->translateLoc(loc, scope);
2268 }
2269 
2270 llvm::DIExpression *
2271 ModuleTranslation::translateExpression(LLVM::DIExpressionAttr attr) {
2272  return debugTranslation->translateExpression(attr);
2273 }
2274 
2275 llvm::DIGlobalVariableExpression *
2277  LLVM::DIGlobalVariableExpressionAttr attr) {
2278  return debugTranslation->translateGlobalVariableExpression(attr);
2279 }
2280 
2282  return debugTranslation->translate(attr);
2283 }
2284 
2285 llvm::RoundingMode
2286 ModuleTranslation::translateRoundingMode(LLVM::RoundingMode rounding) {
2287  return convertRoundingModeToLLVM(rounding);
2288 }
2289 
2291  LLVM::FPExceptionBehavior exceptionBehavior) {
2292  return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
2293 }
2294 
2295 llvm::NamedMDNode *
2297  return llvmModule->getOrInsertNamedMetadata(name);
2298 }
2299 
2300 static std::unique_ptr<llvm::Module>
2301 prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
2302  StringRef name) {
2303  m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
2304  auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
2305  if (auto dataLayoutAttr =
2306  m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
2307  llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
2308  } else {
2309  FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(""));
2310  if (auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
2311  if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
2312  llvmDataLayout =
2313  translateDataLayout(spec, DataLayout(iface), m->getLoc());
2314  }
2315  } else if (auto mod = dyn_cast<ModuleOp>(m)) {
2316  if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
2317  llvmDataLayout =
2318  translateDataLayout(spec, DataLayout(mod), m->getLoc());
2319  }
2320  }
2321  if (failed(llvmDataLayout))
2322  return nullptr;
2323  llvmModule->setDataLayout(*llvmDataLayout);
2324  }
2325  if (auto targetTripleAttr =
2326  m->getDiscardableAttr(LLVM::LLVMDialect::getTargetTripleAttrName()))
2327  llvmModule->setTargetTriple(
2328  llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
2329 
2330  if (auto asmAttr = m->getDiscardableAttr(
2331  LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
2332  auto asmArrayAttr = dyn_cast<ArrayAttr>(asmAttr);
2333  if (!asmArrayAttr) {
2334  m->emitError("expected an array attribute for a module level asm");
2335  return nullptr;
2336  }
2337 
2338  for (Attribute elt : asmArrayAttr) {
2339  auto asmStrAttr = dyn_cast<StringAttr>(elt);
2340  if (!asmStrAttr) {
2341  m->emitError(
2342  "expected a string attribute for each entry of a module level asm");
2343  return nullptr;
2344  }
2345  llvmModule->appendModuleInlineAsm(asmStrAttr.getValue());
2346  }
2347  }
2348 
2349  return llvmModule;
2350 }
2351 
2352 std::unique_ptr<llvm::Module>
2353 mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
2354  StringRef name, bool disableVerification) {
2355  if (!satisfiesLLVMModule(module)) {
2356  module->emitOpError("can not be translated to an LLVMIR module");
2357  return nullptr;
2358  }
2359 
2360  std::unique_ptr<llvm::Module> llvmModule =
2361  prepareLLVMModule(module, llvmContext, name);
2362  if (!llvmModule)
2363  return nullptr;
2364 
2367 
2368  ModuleTranslation translator(module, std::move(llvmModule));
2369  llvm::IRBuilder<llvm::TargetFolder> llvmBuilder(
2370  llvmContext,
2371  llvm::TargetFolder(translator.getLLVMModule()->getDataLayout()));
2372 
2373  // Convert module before functions and operations inside, so dialect
2374  // attributes can be used to change dialect-specific global configurations via
2375  // `amendOperation()`. These configurations can then influence the translation
2376  // of operations afterwards.
2377  if (failed(translator.convertOperation(*module, llvmBuilder)))
2378  return nullptr;
2379 
2380  if (failed(translator.convertComdats()))
2381  return nullptr;
2382  if (failed(translator.convertFunctionSignatures()))
2383  return nullptr;
2384  if (failed(translator.convertGlobalsAndAliases()))
2385  return nullptr;
2386  if (failed(translator.convertIFuncs()))
2387  return nullptr;
2388  if (failed(translator.createTBAAMetadata()))
2389  return nullptr;
2390  if (failed(translator.createIdentMetadata()))
2391  return nullptr;
2392  if (failed(translator.createCommandlineMetadata()))
2393  return nullptr;
2394  if (failed(translator.createDependentLibrariesMetadata()))
2395  return nullptr;
2396 
2397  // Convert other top-level operations if possible.
2398  for (Operation &o : getModuleBody(module).getOperations()) {
2399  if (!isa<LLVM::LLVMFuncOp, LLVM::AliasOp, LLVM::GlobalOp,
2400  LLVM::GlobalCtorsOp, LLVM::GlobalDtorsOp, LLVM::ComdatOp,
2401  LLVM::IFuncOp>(&o) &&
2402  !o.hasTrait<OpTrait::IsTerminator>() &&
2403  failed(translator.convertOperation(o, llvmBuilder))) {
2404  return nullptr;
2405  }
2406  }
2407 
2408  // Operations in function bodies with symbolic references must be converted
2409  // after the top-level operations they refer to are declared, so we do it
2410  // last.
2411  if (failed(translator.convertFunctions()))
2412  return nullptr;
2413 
2414  // Now that all MLIR blocks are resolved into LLVM ones, patch block address
2415  // constants to point to the correct blocks.
2416  if (failed(translator.convertUnresolvedBlockAddress()))
2417  return nullptr;
2418 
2419  // Add the necessary debug info module flags, if they were not encoded in MLIR
2420  // beforehand.
2421  translator.debugTranslation->addModuleFlagsIfNotPresent();
2422 
2423  // Call the OpenMP IR Builder callbacks prior to verifying the module
2424  if (auto *ompBuilder = translator.getOpenMPBuilder())
2425  ompBuilder->finalize();
2426 
2427  if (!disableVerification &&
2428  llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
2429  return nullptr;
2430 
2431  return std::move(translator.llvmModule);
2432 }
static MLIRContext * getContext(OpFoldResult val)
union mlir::linalg::@1242::ArityGroupAndKind::Kind kind
@ 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 FailureOr< llvm::Attribute > convertMLIRAttributeToLLVM(Location loc, llvm::LLVMContext &ctx, StringRef key, StringRef value=StringRef())
Attempts to translate an MLIR attribute identified by key, optionally with the given value,...
static void convertFunctionAttributes(LLVMFuncOp func, llvm::Function *llvmFunc)
Converts function attributes from func and attaches them to llvmFunc.
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 FailureOr< llvm::AttrBuilder > convertMLIRAttributesToLLVM(Location loc, llvm::LLVMContext &ctx, ArrayAttr arrayAttr, StringRef arrayAttrName)
Converts the MLIR attributes listed in the given array attribute into LLVM attributes.
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 LogicalResult convertParameterAttr(llvm::AttrBuilder &attrBuilder, llvm::Attribute::AttrKind llvmKind, NamedAttribute namedAttr, ModuleTranslation &moduleTranslation, Location loc)
static void convertFunctionMemoryAttributes(LLVMFuncOp func, llvm::Function *llvmFunc)
Converts memory effect attributes from func and attaches them 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:91
ArrayRef< char > getData() const
Return the raw underlying data of this blob.
Definition: AsmState.h:145
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
MLIRContext * getContext() const
Return the context this attribute belongs to.
Definition: Attributes.cpp:37
Block represents an ordered list of Operations.
Definition: Block.h:33
Operation * getTerminator()
Get the terminator operation of this block.
Definition: Block.cpp:244
iterator_range< pred_iterator > getPredecessors()
Definition: Block.h:240
BlockArgListType getArguments()
Definition: Block.h:87
Operation & front()
Definition: Block.h:153
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
Definition: Block.h:212
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:28
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 setDereferenceableMetadata(DereferenceableOpInterface op, llvm::Instruction *inst)
Sets LLVM dereferenceable metadata for operations that have dereferenceable attributes.
void setBranchWeightsMetadata(WeightedBranchOpInterface op)
Sets LLVM profiling metadata for operations that have branch weights.
SymbolTableCollection & symbolTable()
LogicalResult convertArgAndResultAttrs(ArgAndResultAttrsOpInterface attrsOp, llvm::CallBase *call, ArrayRef< unsigned > immArgPositions={})
Converts argument and result attributes from attrsOp to LLVM IR attributes on the call instruction.
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::GlobalValue * lookupAlias(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global alias va...
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.
void setDisjointFlag(Operation *op, llvm::Value *value)
Sets the disjoint flag attribute for the exported instruction value given the original operation op.
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::BasicBlock * lookupBlockAddress(BlockAddressAttr attr) const
Finds the LLVM basic block that corresponds to the given BlockAddressAttr.
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:178
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:76
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
Definition: MLIRContext.h:100
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:164
Attribute getValue() const
Return the value of the attribute.
Definition: Attributes.h:179
This class provides the API for ops that are known to be terminators.
Definition: OpDefinition.h:773
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
Attribute getDiscardableAttr(StringRef name)
Access a discardable attribute by name, returns a null Attribute if the discardable attribute does no...
Definition: Operation.h:453
Value getOperand(unsigned idx)
Definition: Operation.h:350
AttrClass getAttrOfType(StringAttr name)
Definition: Operation.h:550
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Definition: Operation.h:534
Block * getSuccessor(unsigned index)
Definition: Operation.h:708
unsigned getNumSuccessors()
Definition: Operation.h:706
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition: Operation.h:407
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:797
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:216
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:267
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Definition: Operation.h:686
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:637
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition: Operation.h:378
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Definition: Operation.cpp:672
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.
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
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:387
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:185
Type getType() const
Return the type of this value.
Definition: Value.h:105
use_iterator use_begin() const
Definition: Value.h:184
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.
Operation * parentLLVMModule(Operation *op)
Lookup parent Module satisfying LLVM conditions on the Module Operation.
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:795
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'.
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition: Remarks.h:491
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:304
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...