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() && !elementType->isFPOrFPVectorTy()) {
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 = llvm::sum_of(opBundleSizes);
926  assert(numOpBundleOperands <= intrOp->getNumOperands() &&
927  "operand bundle operands is more than the number of operands");
928 
929  ValueRange operands = intrOp->getOperands().take_back(numOpBundleOperands);
930  size_t nextOperandIdx = 0;
931  opBundles.reserve(opBundleSizesAttr.size());
932 
933  for (auto [opBundleTagAttr, bundleSize] :
934  llvm::zip(opBundleTagsAttr, opBundleSizes)) {
935  auto bundleTag = cast<StringAttr>(opBundleTagAttr).str();
936  auto bundleOperands = moduleTranslation.lookupValues(
937  operands.slice(nextOperandIdx, bundleSize));
938  opBundles.emplace_back(std::move(bundleTag), std::move(bundleOperands));
939  nextOperandIdx += bundleSize;
940  }
941  }
942 
943  // Map operands and attributes to LLVM values.
944  auto opOperands = intrOp->getOperands().drop_back(numOpBundleOperands);
945  auto operands = moduleTranslation.lookupValues(opOperands);
946  SmallVector<llvm::Value *> args(immArgPositions.size() + operands.size());
947  for (auto [immArgPos, immArgName] :
948  llvm::zip(immArgPositions, immArgAttrNames)) {
949  auto attr = llvm::cast<TypedAttr>(intrOp->getAttr(immArgName));
950  assert(attr.getType().isIntOrFloat() && "expected int or float immarg");
951  auto *type = moduleTranslation.convertType(attr.getType());
952  args[immArgPos] = LLVM::detail::getLLVMConstant(
953  type, attr, intrOp->getLoc(), moduleTranslation);
954  }
955  unsigned opArg = 0;
956  for (auto &arg : args) {
957  if (!arg)
958  arg = operands[opArg++];
959  }
960 
961  // Resolve overloaded intrinsic declaration.
962  SmallVector<llvm::Type *> overloadedTypes;
963  for (unsigned overloadedResultIdx : overloadedResults) {
964  if (numResults > 1) {
965  // More than one result is mapped to an LLVM struct.
966  overloadedTypes.push_back(moduleTranslation.convertType(
967  llvm::cast<LLVM::LLVMStructType>(intrOp->getResult(0).getType())
968  .getBody()[overloadedResultIdx]));
969  } else {
970  overloadedTypes.push_back(
971  moduleTranslation.convertType(intrOp->getResult(0).getType()));
972  }
973  }
974  for (unsigned overloadedOperandIdx : overloadedOperands)
975  overloadedTypes.push_back(args[overloadedOperandIdx]->getType());
976  llvm::Module *module = builder.GetInsertBlock()->getModule();
977  llvm::Function *llvmIntr = llvm::Intrinsic::getOrInsertDeclaration(
978  module, intrinsic, overloadedTypes);
979 
980  return builder.CreateCall(llvmIntr, args, opBundles);
981 }
982 
983 /// Given a single MLIR operation, create the corresponding LLVM IR operation
984 /// using the `builder`.
985 LogicalResult ModuleTranslation::convertOperation(Operation &op,
986  llvm::IRBuilderBase &builder,
987  bool recordInsertions) {
988  const LLVMTranslationDialectInterface *opIface = iface.getInterfaceFor(&op);
989  if (!opIface)
990  return op.emitError("cannot be converted to LLVM IR: missing "
991  "`LLVMTranslationDialectInterface` registration for "
992  "dialect for op: ")
993  << op.getName();
994 
995  InstructionCapturingInserter::CollectionScope scope(builder,
996  recordInsertions);
997  if (failed(opIface->convertOperation(&op, builder, *this)))
998  return op.emitError("LLVM Translation failed for operation: ")
999  << op.getName();
1000 
1001  return convertDialectAttributes(&op, scope.getCapturedInstructions());
1002 }
1003 
1004 /// Convert block to LLVM IR. Unless `ignoreArguments` is set, emit PHI nodes
1005 /// to define values corresponding to the MLIR block arguments. These nodes
1006 /// are not connected to the source basic blocks, which may not exist yet. Uses
1007 /// `builder` to construct the LLVM IR. Expects the LLVM IR basic block to have
1008 /// been created for `bb` and included in the block mapping. Inserts new
1009 /// instructions at the end of the block and leaves `builder` in a state
1010 /// suitable for further insertion into the end of the block.
1011 LogicalResult ModuleTranslation::convertBlockImpl(Block &bb,
1012  bool ignoreArguments,
1013  llvm::IRBuilderBase &builder,
1014  bool recordInsertions) {
1015  builder.SetInsertPoint(lookupBlock(&bb));
1016  auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
1017 
1018  // Before traversing operations, make block arguments available through
1019  // value remapping and PHI nodes, but do not add incoming edges for the PHI
1020  // nodes just yet: those values may be defined by this or following blocks.
1021  // This step is omitted if "ignoreArguments" is set. The arguments of the
1022  // first block have been already made available through the remapping of
1023  // LLVM function arguments.
1024  if (!ignoreArguments) {
1025  auto predecessors = bb.getPredecessors();
1026  unsigned numPredecessors =
1027  std::distance(predecessors.begin(), predecessors.end());
1028  for (auto arg : bb.getArguments()) {
1029  auto wrappedType = arg.getType();
1030  if (!isCompatibleType(wrappedType))
1031  return emitError(bb.front().getLoc(),
1032  "block argument does not have an LLVM type");
1033  builder.SetCurrentDebugLocation(
1034  debugTranslation->translateLoc(arg.getLoc(), subprogram));
1035  llvm::Type *type = convertType(wrappedType);
1036  llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
1037  mapValue(arg, phi);
1038  }
1039  }
1040 
1041  // Traverse operations.
1042  for (auto &op : bb) {
1043  // Set the current debug location within the builder.
1044  builder.SetCurrentDebugLocation(
1045  debugTranslation->translateLoc(op.getLoc(), subprogram));
1046 
1047  if (failed(convertOperation(op, builder, recordInsertions)))
1048  return failure();
1049 
1050  // Set the branch weight metadata on the translated instruction.
1051  if (auto iface = dyn_cast<WeightedBranchOpInterface>(op))
1052  setBranchWeightsMetadata(iface);
1053  }
1054 
1055  return success();
1056 }
1057 
1058 /// A helper method to get the single Block in an operation honoring LLVM's
1059 /// module requirements.
1060 static Block &getModuleBody(Operation *module) {
1061  return module->getRegion(0).front();
1062 }
1063 
1064 /// A helper method to decide if a constant must not be set as a global variable
1065 /// initializer. For an external linkage variable, the variable with an
1066 /// initializer is considered externally visible and defined in this module, the
1067 /// variable without an initializer is externally available and is defined
1068 /// elsewhere.
1069 static bool shouldDropGlobalInitializer(llvm::GlobalValue::LinkageTypes linkage,
1070  llvm::Constant *cst) {
1071  return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
1072  linkage == llvm::GlobalVariable::ExternalWeakLinkage;
1073 }
1074 
1075 /// Sets the runtime preemption specifier of `gv` to dso_local if
1076 /// `dsoLocalRequested` is true, otherwise it is left unchanged.
1077 static void addRuntimePreemptionSpecifier(bool dsoLocalRequested,
1078  llvm::GlobalValue *gv) {
1079  if (dsoLocalRequested)
1080  gv->setDSOLocal(true);
1081 }
1082 
1083 /// Attempts to translate an MLIR attribute identified by `key`, optionally with
1084 /// the given `value`, into an LLVM IR attribute. Reports errors at `loc` if
1085 /// any. If the attribute name corresponds to a known LLVM IR attribute kind,
1086 /// creates the LLVM attribute of that kind; otherwise, keeps it as a string
1087 /// attribute. Performs additional checks for attributes known to have or not
1088 /// have a value in order to avoid assertions inside LLVM upon construction.
1089 static FailureOr<llvm::Attribute>
1090 convertMLIRAttributeToLLVM(Location loc, llvm::LLVMContext &ctx, StringRef key,
1091  StringRef value = StringRef()) {
1092  auto kind = llvm::Attribute::getAttrKindFromName(key);
1093  if (kind == llvm::Attribute::None)
1094  return llvm::Attribute::get(ctx, key, value);
1095 
1096  if (llvm::Attribute::isIntAttrKind(kind)) {
1097  if (value.empty())
1098  return emitError(loc) << "LLVM attribute '" << key << "' expects a value";
1099 
1100  int64_t result;
1101  if (!value.getAsInteger(/*Radix=*/0, result))
1102  return llvm::Attribute::get(ctx, kind, result);
1103  return llvm::Attribute::get(ctx, key, value);
1104  }
1105 
1106  if (!value.empty())
1107  return emitError(loc) << "LLVM attribute '" << key
1108  << "' does not expect a value, found '" << value
1109  << "'";
1110 
1111  return llvm::Attribute::get(ctx, kind);
1112 }
1113 
1114 /// Converts the MLIR attributes listed in the given array attribute into LLVM
1115 /// attributes. Returns an `AttrBuilder` containing the converted attributes.
1116 /// Reports error to `loc` if any and returns immediately. Expects `arrayAttr`
1117 /// to contain either string attributes, treated as value-less LLVM attributes,
1118 /// or array attributes containing two string attributes, with the first string
1119 /// being the name of the corresponding LLVM attribute and the second string
1120 /// beings its value. Note that even integer attributes are expected to have
1121 /// their values expressed as strings.
1122 static FailureOr<llvm::AttrBuilder>
1123 convertMLIRAttributesToLLVM(Location loc, llvm::LLVMContext &ctx,
1124  ArrayAttr arrayAttr, StringRef arrayAttrName) {
1125  llvm::AttrBuilder attrBuilder(ctx);
1126  if (!arrayAttr)
1127  return attrBuilder;
1128 
1129  for (Attribute attr : arrayAttr) {
1130  if (auto stringAttr = dyn_cast<StringAttr>(attr)) {
1131  FailureOr<llvm::Attribute> llvmAttr =
1132  convertMLIRAttributeToLLVM(loc, ctx, stringAttr.getValue());
1133  if (failed(llvmAttr))
1134  return failure();
1135  attrBuilder.addAttribute(*llvmAttr);
1136  continue;
1137  }
1138 
1139  auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1140  if (!arrayAttr || arrayAttr.size() != 2)
1141  return emitError(loc) << "expected '" << arrayAttrName
1142  << "' to contain string or array attributes";
1143 
1144  auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1145  auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1146  if (!keyAttr || !valueAttr)
1147  return emitError(loc) << "expected arrays within '" << arrayAttrName
1148  << "' to contain two strings";
1149 
1150  FailureOr<llvm::Attribute> llvmAttr = convertMLIRAttributeToLLVM(
1151  loc, ctx, keyAttr.getValue(), valueAttr.getValue());
1152  if (failed(llvmAttr))
1153  return failure();
1154  attrBuilder.addAttribute(*llvmAttr);
1155  }
1156 
1157  return attrBuilder;
1158 }
1159 
1160 LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
1161  // Mapping from compile unit to its respective set of global variables.
1163 
1164  // First, create all global variables and global aliases in LLVM IR. A global
1165  // or alias body may refer to another global/alias or itself, so all the
1166  // mapping needs to happen prior to body conversion.
1167 
1168  // Create all llvm::GlobalVariable
1169  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1170  llvm::Type *type = convertType(op.getType());
1171  llvm::Constant *cst = nullptr;
1172  if (op.getValueOrNull()) {
1173  // String attributes are treated separately because they cannot appear as
1174  // in-function constants and are thus not supported by getLLVMConstant.
1175  if (auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1176  cst = llvm::ConstantDataArray::getString(
1177  llvmModule->getContext(), strAttr.getValue(), /*AddNull=*/false);
1178  type = cst->getType();
1179  } else if (!(cst = getLLVMConstant(type, op.getValueOrNull(), op.getLoc(),
1180  *this))) {
1181  return failure();
1182  }
1183  }
1184 
1185  auto linkage = convertLinkageToLLVM(op.getLinkage());
1186 
1187  // LLVM IR requires constant with linkage other than external or weak
1188  // external to have initializers. If MLIR does not provide an initializer,
1189  // default to undef.
1190  bool dropInitializer = shouldDropGlobalInitializer(linkage, cst);
1191  if (!dropInitializer && !cst)
1192  cst = llvm::UndefValue::get(type);
1193  else if (dropInitializer && cst)
1194  cst = nullptr;
1195 
1196  auto *var = new llvm::GlobalVariable(
1197  *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1198  /*InsertBefore=*/nullptr,
1199  op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1200  : llvm::GlobalValue::NotThreadLocal,
1201  op.getAddrSpace(), op.getExternallyInitialized());
1202 
1203  if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1204  auto selectorOp = cast<ComdatSelectorOp>(
1206  var->setComdat(comdatMapping.lookup(selectorOp));
1207  }
1208 
1209  if (op.getUnnamedAddr().has_value())
1210  var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1211 
1212  if (op.getSection().has_value())
1213  var->setSection(*op.getSection());
1214 
1215  addRuntimePreemptionSpecifier(op.getDsoLocal(), var);
1216 
1217  std::optional<uint64_t> alignment = op.getAlignment();
1218  if (alignment.has_value())
1219  var->setAlignment(llvm::MaybeAlign(alignment.value()));
1220 
1221  var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1222 
1223  globalsMapping.try_emplace(op, var);
1224 
1225  // Add debug information if present.
1226  if (op.getDbgExprs()) {
1227  for (auto exprAttr :
1228  op.getDbgExprs()->getAsRange<DIGlobalVariableExpressionAttr>()) {
1229  llvm::DIGlobalVariableExpression *diGlobalExpr =
1230  debugTranslation->translateGlobalVariableExpression(exprAttr);
1231  llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1232  var->addDebugInfo(diGlobalExpr);
1233 
1234  // There is no `globals` field in DICompileUnitAttr which can be
1235  // directly assigned to DICompileUnit. We have to build the list by
1236  // looking at the dbgExpr of all the GlobalOps. The scope of the
1237  // variable is used to get the DICompileUnit in which to add it. But
1238  // there are cases where the scope of a global does not directly point
1239  // to the DICompileUnit and we have to do a bit more work to get to
1240  // it. Some of those cases are:
1241  //
1242  // 1. For the languages that support modules, the scope hierarchy can
1243  // be variable -> DIModule -> DICompileUnit
1244  //
1245  // 2. For the Fortran common block variable, the scope hierarchy can
1246  // be variable -> DICommonBlock -> DISubprogram -> DICompileUnit
1247  //
1248  // 3. For entities like static local variables in C or variable with
1249  // SAVE attribute in Fortran, the scope hierarchy can be
1250  // variable -> DISubprogram -> DICompileUnit
1251  llvm::DIScope *scope = diGlobalVar->getScope();
1252  if (auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1253  scope = mod->getScope();
1254  else if (auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
1255  if (auto *sp =
1256  dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
1257  scope = sp->getUnit();
1258  } else if (auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
1259  scope = sp->getUnit();
1260 
1261  // Get the compile unit (scope) of the the global variable.
1262  if (llvm::DICompileUnit *compileUnit =
1263  dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1264  // Update the compile unit with this incoming global variable
1265  // expression during the finalizing step later.
1266  allGVars[compileUnit].push_back(diGlobalExpr);
1267  }
1268  }
1269  }
1270 
1271  // Forward the target-specific attributes to LLVM.
1272  FailureOr<llvm::AttrBuilder> convertedTargetSpecificAttrs =
1274  op.getTargetSpecificAttrsAttr(),
1275  op.getTargetSpecificAttrsAttrName());
1276  if (failed(convertedTargetSpecificAttrs))
1277  return failure();
1278  var->addAttributes(*convertedTargetSpecificAttrs);
1279  }
1280 
1281  // Create all llvm::GlobalAlias
1282  for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1283  llvm::Type *type = convertType(op.getType());
1284  llvm::Constant *cst = nullptr;
1285  llvm::GlobalValue::LinkageTypes linkage =
1286  convertLinkageToLLVM(op.getLinkage());
1287  llvm::Module &llvmMod = *llvmModule;
1288 
1289  // Note address space and aliasee info isn't set just yet.
1290  llvm::GlobalAlias *var = llvm::GlobalAlias::create(
1291  type, op.getAddrSpace(), linkage, op.getSymName(), /*placeholder*/ cst,
1292  &llvmMod);
1293 
1294  var->setThreadLocalMode(op.getThreadLocal_()
1295  ? llvm::GlobalAlias::GeneralDynamicTLSModel
1296  : llvm::GlobalAlias::NotThreadLocal);
1297 
1298  // Note there is no need to setup the comdat because GlobalAlias calls into
1299  // the aliasee comdat information automatically.
1300 
1301  if (op.getUnnamedAddr().has_value())
1302  var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1303 
1304  var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1305 
1306  aliasesMapping.try_emplace(op, var);
1307  }
1308 
1309  // Convert global variable bodies.
1310  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1311  if (Block *initializer = op.getInitializerBlock()) {
1312  llvm::IRBuilder<llvm::TargetFolder> builder(
1313  llvmModule->getContext(),
1314  llvm::TargetFolder(llvmModule->getDataLayout()));
1315 
1316  [[maybe_unused]] int numConstantsHit = 0;
1317  [[maybe_unused]] int numConstantsErased = 0;
1318  DenseMap<llvm::ConstantAggregate *, int> constantAggregateUseMap;
1319 
1320  for (auto &op : initializer->without_terminator()) {
1321  if (failed(convertOperation(op, builder)))
1322  return emitError(op.getLoc(), "fail to convert global initializer");
1323  auto *cst = dyn_cast<llvm::Constant>(lookupValue(op.getResult(0)));
1324  if (!cst)
1325  return emitError(op.getLoc(), "unemittable constant value");
1326 
1327  // When emitting an LLVM constant, a new constant is created and the old
1328  // constant may become dangling and take space. We should remove the
1329  // dangling constants to avoid memory explosion especially for constant
1330  // arrays whose number of elements is large.
1331  // Because multiple operations may refer to the same constant, we need
1332  // to count the number of uses of each constant array and remove it only
1333  // when the count becomes zero.
1334  if (auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1335  numConstantsHit++;
1336  Value result = op.getResult(0);
1337  int numUsers = std::distance(result.use_begin(), result.use_end());
1338  auto [iterator, inserted] =
1339  constantAggregateUseMap.try_emplace(agg, numUsers);
1340  if (!inserted) {
1341  // Key already exists, update the value
1342  iterator->second += numUsers;
1343  }
1344  }
1345  // Scan the operands of the operation to decrement the use count of
1346  // constants. Erase the constant if the use count becomes zero.
1347  for (Value v : op.getOperands()) {
1348  auto cst = dyn_cast<llvm::ConstantAggregate>(lookupValue(v));
1349  if (!cst)
1350  continue;
1351  auto iter = constantAggregateUseMap.find(cst);
1352  assert(iter != constantAggregateUseMap.end() && "constant not found");
1353  iter->second--;
1354  if (iter->second == 0) {
1355  // NOTE: cannot call removeDeadConstantUsers() here because it
1356  // may remove the constant which has uses not be converted yet.
1357  if (cst->user_empty()) {
1358  cst->destroyConstant();
1359  numConstantsErased++;
1360  }
1361  constantAggregateUseMap.erase(iter);
1362  }
1363  }
1364  }
1365 
1366  ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1367  llvm::Constant *cst =
1368  cast<llvm::Constant>(lookupValue(ret.getOperand(0)));
1369  auto *global = cast<llvm::GlobalVariable>(lookupGlobal(op));
1370  if (!shouldDropGlobalInitializer(global->getLinkage(), cst))
1371  global->setInitializer(cst);
1372 
1373  // Try to remove the dangling constants again after all operations are
1374  // converted.
1375  for (auto it : constantAggregateUseMap) {
1376  auto cst = it.first;
1377  cst->removeDeadConstantUsers();
1378  if (cst->user_empty()) {
1379  cst->destroyConstant();
1380  numConstantsErased++;
1381  }
1382  }
1383 
1384  LLVM_DEBUG(llvm::dbgs()
1385  << "Convert initializer for " << op.getName() << "\n";
1386  llvm::dbgs() << numConstantsHit << " new constants hit\n";
1387  llvm::dbgs()
1388  << numConstantsErased << " dangling constants erased\n";);
1389  }
1390  }
1391 
1392  // Convert llvm.mlir.global_ctors and dtors.
1393  for (Operation &op : getModuleBody(mlirModule)) {
1394  auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1395  auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1396  if (!ctorOp && !dtorOp)
1397  continue;
1398 
1399  // The empty / zero initialized version of llvm.global_(c|d)tors cannot be
1400  // handled by appendGlobalFn logic below, which just ignores empty (c|d)tor
1401  // lists. Make sure it gets emitted.
1402  if ((ctorOp && ctorOp.getCtors().empty()) ||
1403  (dtorOp && dtorOp.getDtors().empty())) {
1404  llvm::IRBuilder<llvm::TargetFolder> builder(
1405  llvmModule->getContext(),
1406  llvm::TargetFolder(llvmModule->getDataLayout()));
1407  llvm::Type *eltTy = llvm::StructType::get(
1408  builder.getInt32Ty(), builder.getPtrTy(), builder.getPtrTy());
1409  llvm::ArrayType *at = llvm::ArrayType::get(eltTy, 0);
1410  llvm::Constant *zeroInit = llvm::Constant::getNullValue(at);
1411  (void)new llvm::GlobalVariable(
1412  *llvmModule, zeroInit->getType(), false,
1413  llvm::GlobalValue::AppendingLinkage, zeroInit,
1414  ctorOp ? "llvm.global_ctors" : "llvm.global_dtors");
1415  } else {
1416  auto range = ctorOp
1417  ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1418  : llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1419  auto appendGlobalFn =
1420  ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1421  for (const auto &[sym, prio] : range) {
1422  llvm::Function *f =
1423  lookupFunction(cast<FlatSymbolRefAttr>(sym).getValue());
1424  appendGlobalFn(*llvmModule, f, cast<IntegerAttr>(prio).getInt(),
1425  /*Data=*/nullptr);
1426  }
1427  }
1428  }
1429 
1430  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1431  if (failed(convertDialectAttributes(op, {})))
1432  return failure();
1433 
1434  // Finally, update the compile units their respective sets of global variables
1435  // created earlier.
1436  for (const auto &[compileUnit, globals] : allGVars) {
1437  compileUnit->replaceGlobalVariables(
1438  llvm::MDTuple::get(getLLVMContext(), globals));
1439  }
1440 
1441  // Convert global alias bodies.
1442  for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1443  Block &initializer = op.getInitializerBlock();
1444  llvm::IRBuilder<llvm::TargetFolder> builder(
1445  llvmModule->getContext(),
1446  llvm::TargetFolder(llvmModule->getDataLayout()));
1447 
1448  for (mlir::Operation &op : initializer.without_terminator()) {
1449  if (failed(convertOperation(op, builder)))
1450  return emitError(op.getLoc(), "fail to convert alias initializer");
1451  if (!isa<llvm::Constant>(lookupValue(op.getResult(0))))
1452  return emitError(op.getLoc(), "unemittable constant value");
1453  }
1454 
1455  auto ret = cast<ReturnOp>(initializer.getTerminator());
1456  auto *cst = cast<llvm::Constant>(lookupValue(ret.getOperand(0)));
1457  assert(aliasesMapping.count(op));
1458  auto *alias = cast<llvm::GlobalAlias>(aliasesMapping[op]);
1459  alias->setAliasee(cst);
1460  }
1461 
1462  for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>())
1463  if (failed(convertDialectAttributes(op, {})))
1464  return failure();
1465 
1466  return success();
1467 }
1468 
1469 /// Return a representation of `value` as metadata.
1470 static llvm::Metadata *convertIntegerToMetadata(llvm::LLVMContext &context,
1471  const llvm::APInt &value) {
1472  llvm::Constant *constant = llvm::ConstantInt::get(context, value);
1473  return llvm::ConstantAsMetadata::get(constant);
1474 }
1475 
1476 /// Return a representation of `value` as an MDNode.
1477 static llvm::MDNode *convertIntegerToMDNode(llvm::LLVMContext &context,
1478  const llvm::APInt &value) {
1479  return llvm::MDNode::get(context, convertIntegerToMetadata(context, value));
1480 }
1481 
1482 /// Return an MDNode encoding `vec_type_hint` metadata.
1483 static llvm::MDNode *convertVecTypeHintToMDNode(llvm::LLVMContext &context,
1484  llvm::Type *type,
1485  bool isSigned) {
1486  llvm::Metadata *typeMD =
1488  llvm::Metadata *isSignedMD =
1489  convertIntegerToMetadata(context, llvm::APInt(32, isSigned ? 1 : 0));
1490  return llvm::MDNode::get(context, {typeMD, isSignedMD});
1491 }
1492 
1493 /// Return an MDNode with a tuple given by the values in `values`.
1494 static llvm::MDNode *convertIntegerArrayToMDNode(llvm::LLVMContext &context,
1495  ArrayRef<int32_t> values) {
1497  llvm::transform(
1498  values, std::back_inserter(mdValues), [&context](int32_t value) {
1499  return convertIntegerToMetadata(context, llvm::APInt(32, value));
1500  });
1501  return llvm::MDNode::get(context, mdValues);
1502 }
1503 
1504 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1505  // Clear the block, branch value mappings, they are only relevant within one
1506  // function.
1507  blockMapping.clear();
1508  valueMapping.clear();
1509  branchMapping.clear();
1510  llvm::Function *llvmFunc = lookupFunction(func.getName());
1511 
1512  // Add function arguments to the value remapping table.
1513  for (auto [mlirArg, llvmArg] :
1514  llvm::zip(func.getArguments(), llvmFunc->args()))
1515  mapValue(mlirArg, &llvmArg);
1516 
1517  // Check the personality and set it.
1518  if (func.getPersonality()) {
1519  llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1520  if (llvm::Constant *pfunc = getLLVMConstant(ty, func.getPersonalityAttr(),
1521  func.getLoc(), *this))
1522  llvmFunc->setPersonalityFn(pfunc);
1523  }
1524 
1525  if (std::optional<StringRef> section = func.getSection())
1526  llvmFunc->setSection(*section);
1527 
1528  if (func.getArmStreaming())
1529  llvmFunc->addFnAttr("aarch64_pstate_sm_enabled");
1530  else if (func.getArmLocallyStreaming())
1531  llvmFunc->addFnAttr("aarch64_pstate_sm_body");
1532  else if (func.getArmStreamingCompatible())
1533  llvmFunc->addFnAttr("aarch64_pstate_sm_compatible");
1534 
1535  if (func.getArmNewZa())
1536  llvmFunc->addFnAttr("aarch64_new_za");
1537  else if (func.getArmInZa())
1538  llvmFunc->addFnAttr("aarch64_in_za");
1539  else if (func.getArmOutZa())
1540  llvmFunc->addFnAttr("aarch64_out_za");
1541  else if (func.getArmInoutZa())
1542  llvmFunc->addFnAttr("aarch64_inout_za");
1543  else if (func.getArmPreservesZa())
1544  llvmFunc->addFnAttr("aarch64_preserves_za");
1545 
1546  if (auto targetCpu = func.getTargetCpu())
1547  llvmFunc->addFnAttr("target-cpu", *targetCpu);
1548 
1549  if (auto tuneCpu = func.getTuneCpu())
1550  llvmFunc->addFnAttr("tune-cpu", *tuneCpu);
1551 
1552  if (auto reciprocalEstimates = func.getReciprocalEstimates())
1553  llvmFunc->addFnAttr("reciprocal-estimates", *reciprocalEstimates);
1554 
1555  if (auto preferVectorWidth = func.getPreferVectorWidth())
1556  llvmFunc->addFnAttr("prefer-vector-width", *preferVectorWidth);
1557 
1558  if (auto attr = func.getVscaleRange())
1559  llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1560  getLLVMContext(), attr->getMinRange().getInt(),
1561  attr->getMaxRange().getInt()));
1562 
1563  if (auto unsafeFpMath = func.getUnsafeFpMath())
1564  llvmFunc->addFnAttr("unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1565 
1566  if (auto noInfsFpMath = func.getNoInfsFpMath())
1567  llvmFunc->addFnAttr("no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1568 
1569  if (auto noNansFpMath = func.getNoNansFpMath())
1570  llvmFunc->addFnAttr("no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1571 
1572  if (auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1573  llvmFunc->addFnAttr("no-signed-zeros-fp-math",
1574  llvm::toStringRef(*noSignedZerosFpMath));
1575 
1576  if (auto denormalFpMath = func.getDenormalFpMath())
1577  llvmFunc->addFnAttr("denormal-fp-math", *denormalFpMath);
1578 
1579  if (auto denormalFpMathF32 = func.getDenormalFpMathF32())
1580  llvmFunc->addFnAttr("denormal-fp-math-f32", *denormalFpMathF32);
1581 
1582  if (auto fpContract = func.getFpContract())
1583  llvmFunc->addFnAttr("fp-contract", *fpContract);
1584 
1585  if (auto instrumentFunctionEntry = func.getInstrumentFunctionEntry())
1586  llvmFunc->addFnAttr("instrument-function-entry", *instrumentFunctionEntry);
1587 
1588  if (auto instrumentFunctionExit = func.getInstrumentFunctionExit())
1589  llvmFunc->addFnAttr("instrument-function-exit", *instrumentFunctionExit);
1590 
1591  // First, create all blocks so we can jump to them.
1592  llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1593  for (auto &bb : func) {
1594  auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1595  llvmBB->insertInto(llvmFunc);
1596  mapBlock(&bb, llvmBB);
1597  }
1598 
1599  // Then, convert blocks one by one in topological order to ensure defs are
1600  // converted before uses.
1601  auto blocks = getBlocksSortedByDominance(func.getBody());
1602  for (Block *bb : blocks) {
1603  CapturingIRBuilder builder(llvmContext,
1604  llvm::TargetFolder(llvmModule->getDataLayout()));
1605  if (failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1606  /*recordInsertions=*/true)))
1607  return failure();
1608  }
1609 
1610  // After all blocks have been traversed and values mapped, connect the PHI
1611  // nodes to the results of preceding blocks.
1612  detail::connectPHINodes(func.getBody(), *this);
1613 
1614  // Finally, convert dialect attributes attached to the function.
1615  return convertDialectAttributes(func, {});
1616 }
1617 
1618 LogicalResult ModuleTranslation::convertDialectAttributes(
1619  Operation *op, ArrayRef<llvm::Instruction *> instructions) {
1620  for (NamedAttribute attribute : op->getDialectAttrs())
1621  if (failed(iface.amendOperation(op, instructions, attribute, *this)))
1622  return failure();
1623  return success();
1624 }
1625 
1626 /// Converts memory effect attributes from `func` and attaches them to
1627 /// `llvmFunc`.
1628 static void convertFunctionMemoryAttributes(LLVMFuncOp func,
1629  llvm::Function *llvmFunc) {
1630  if (!func.getMemoryEffects())
1631  return;
1632 
1633  MemoryEffectsAttr memEffects = func.getMemoryEffectsAttr();
1634 
1635  // Add memory effects incrementally.
1636  llvm::MemoryEffects newMemEffects =
1637  llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1638  convertModRefInfoToLLVM(memEffects.getArgMem()));
1639  newMemEffects |= llvm::MemoryEffects(
1640  llvm::MemoryEffects::Location::InaccessibleMem,
1641  convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1642  newMemEffects |=
1643  llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1644  convertModRefInfoToLLVM(memEffects.getOther()));
1645  llvmFunc->setMemoryEffects(newMemEffects);
1646 }
1647 
1648 /// Converts function attributes from `func` and attaches them to `llvmFunc`.
1649 static void convertFunctionAttributes(LLVMFuncOp func,
1650  llvm::Function *llvmFunc) {
1651  if (func.getNoInlineAttr())
1652  llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1653  if (func.getAlwaysInlineAttr())
1654  llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1655  if (func.getOptimizeNoneAttr())
1656  llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1657  if (func.getConvergentAttr())
1658  llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1659  if (func.getNoUnwindAttr())
1660  llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1661  if (func.getWillReturnAttr())
1662  llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1663  if (TargetFeaturesAttr targetFeatAttr = func.getTargetFeaturesAttr())
1664  llvmFunc->addFnAttr("target-features", targetFeatAttr.getFeaturesString());
1665  if (FramePointerKindAttr fpAttr = func.getFramePointerAttr())
1666  llvmFunc->addFnAttr("frame-pointer", stringifyFramePointerKind(
1667  fpAttr.getFramePointerKind()));
1668  if (UWTableKindAttr uwTableKindAttr = func.getUwtableKindAttr())
1669  llvmFunc->setUWTableKind(
1670  convertUWTableKindToLLVM(uwTableKindAttr.getUwtableKind()));
1671  convertFunctionMemoryAttributes(func, llvmFunc);
1672 }
1673 
1674 /// Converts function attributes from `func` and attaches them to `llvmFunc`.
1675 static void convertFunctionKernelAttributes(LLVMFuncOp func,
1676  llvm::Function *llvmFunc,
1677  ModuleTranslation &translation) {
1678  llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1679 
1680  if (VecTypeHintAttr vecTypeHint = func.getVecTypeHintAttr()) {
1681  Type type = vecTypeHint.getHint().getValue();
1682  llvm::Type *llvmType = translation.convertType(type);
1683  bool isSigned = vecTypeHint.getIsSigned();
1684  llvmFunc->setMetadata(
1685  func.getVecTypeHintAttrName(),
1686  convertVecTypeHintToMDNode(llvmContext, llvmType, isSigned));
1687  }
1688 
1689  if (std::optional<ArrayRef<int32_t>> workGroupSizeHint =
1690  func.getWorkGroupSizeHint()) {
1691  llvmFunc->setMetadata(
1692  func.getWorkGroupSizeHintAttrName(),
1693  convertIntegerArrayToMDNode(llvmContext, *workGroupSizeHint));
1694  }
1695 
1696  if (std::optional<ArrayRef<int32_t>> reqdWorkGroupSize =
1697  func.getReqdWorkGroupSize()) {
1698  llvmFunc->setMetadata(
1699  func.getReqdWorkGroupSizeAttrName(),
1700  convertIntegerArrayToMDNode(llvmContext, *reqdWorkGroupSize));
1701  }
1702 
1703  if (std::optional<uint32_t> intelReqdSubGroupSize =
1704  func.getIntelReqdSubGroupSize()) {
1705  llvmFunc->setMetadata(
1706  func.getIntelReqdSubGroupSizeAttrName(),
1707  convertIntegerToMDNode(llvmContext,
1708  llvm::APInt(32, *intelReqdSubGroupSize)));
1709  }
1710 }
1711 
1712 static LogicalResult convertParameterAttr(llvm::AttrBuilder &attrBuilder,
1713  llvm::Attribute::AttrKind llvmKind,
1714  NamedAttribute namedAttr,
1715  ModuleTranslation &moduleTranslation,
1716  Location loc) {
1718  .Case<TypeAttr>([&](auto typeAttr) {
1719  attrBuilder.addTypeAttr(
1720  llvmKind, moduleTranslation.convertType(typeAttr.getValue()));
1721  return success();
1722  })
1723  .Case<IntegerAttr>([&](auto intAttr) {
1724  attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1725  return success();
1726  })
1727  .Case<UnitAttr>([&](auto) {
1728  attrBuilder.addAttribute(llvmKind);
1729  return success();
1730  })
1731  .Case<LLVM::ConstantRangeAttr>([&](auto rangeAttr) {
1732  attrBuilder.addConstantRangeAttr(
1733  llvmKind,
1734  llvm::ConstantRange(rangeAttr.getLower(), rangeAttr.getUpper()));
1735  return success();
1736  })
1737  .Default([loc](auto) {
1738  return emitError(loc, "unsupported parameter attribute type");
1739  });
1740 }
1741 
1742 FailureOr<llvm::AttrBuilder>
1743 ModuleTranslation::convertParameterAttrs(LLVMFuncOp func, int argIdx,
1744  DictionaryAttr paramAttrs) {
1745  llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1746  auto attrNameToKindMapping = getAttrNameToKindMapping();
1747  Location loc = func.getLoc();
1748 
1749  for (auto namedAttr : paramAttrs) {
1750  auto it = attrNameToKindMapping.find(namedAttr.getName());
1751  if (it != attrNameToKindMapping.end()) {
1752  llvm::Attribute::AttrKind llvmKind = it->second;
1753  if (failed(convertParameterAttr(attrBuilder, llvmKind, namedAttr, *this,
1754  loc)))
1755  return failure();
1756  } else if (namedAttr.getNameDialect()) {
1757  if (failed(iface.convertParameterAttr(func, argIdx, namedAttr, *this)))
1758  return failure();
1759  }
1760  }
1761 
1762  return attrBuilder;
1763 }
1764 
1766  ArgAndResultAttrsOpInterface attrsOp, llvm::CallBase *call,
1767  ArrayRef<unsigned> immArgPositions) {
1768  // Convert the argument attributes.
1769  if (ArrayAttr argAttrsArray = attrsOp.getArgAttrsAttr()) {
1770  unsigned argAttrIdx = 0;
1771  llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
1772  immArgPositions.end());
1773  for (unsigned argIdx : llvm::seq<unsigned>(call->arg_size())) {
1774  if (argAttrIdx >= argAttrsArray.size())
1775  break;
1776  // Skip immediate arguments (they have no entries in argAttrsArray).
1777  if (immArgPositionsSet.contains(argIdx))
1778  continue;
1779  // Skip empty argument attributes.
1780  auto argAttrs = cast<DictionaryAttr>(argAttrsArray[argAttrIdx++]);
1781  if (argAttrs.empty())
1782  continue;
1783  // Convert and add attributes to the call instruction.
1784  FailureOr<llvm::AttrBuilder> attrBuilder =
1785  convertParameterAttrs(attrsOp->getLoc(), argAttrs);
1786  if (failed(attrBuilder))
1787  return failure();
1788  call->addParamAttrs(argIdx, *attrBuilder);
1789  }
1790  }
1791 
1792  // Convert the result attributes.
1793  if (ArrayAttr resAttrsArray = attrsOp.getResAttrsAttr()) {
1794  if (!resAttrsArray.empty()) {
1795  auto resAttrs = cast<DictionaryAttr>(resAttrsArray[0]);
1796  FailureOr<llvm::AttrBuilder> attrBuilder =
1797  convertParameterAttrs(attrsOp->getLoc(), resAttrs);
1798  if (failed(attrBuilder))
1799  return failure();
1800  call->addRetAttrs(*attrBuilder);
1801  }
1802  }
1803 
1804  return success();
1805 }
1806 
1807 FailureOr<llvm::AttrBuilder>
1808 ModuleTranslation::convertParameterAttrs(Location loc,
1809  DictionaryAttr paramAttrs) {
1810  llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1811  auto attrNameToKindMapping = getAttrNameToKindMapping();
1812 
1813  for (auto namedAttr : paramAttrs) {
1814  auto it = attrNameToKindMapping.find(namedAttr.getName());
1815  if (it != attrNameToKindMapping.end()) {
1816  llvm::Attribute::AttrKind llvmKind = it->second;
1817  if (failed(convertParameterAttr(attrBuilder, llvmKind, namedAttr, *this,
1818  loc)))
1819  return failure();
1820  }
1821  }
1822 
1823  return attrBuilder;
1824 }
1825 
1826 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1827  // Declare all functions first because there may be function calls that form a
1828  // call graph with cycles, or global initializers that reference functions.
1829  for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1830  llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1831  function.getName(),
1832  cast<llvm::FunctionType>(convertType(function.getFunctionType())));
1833  llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1834  llvmFunc->setLinkage(convertLinkageToLLVM(function.getLinkage()));
1835  llvmFunc->setCallingConv(convertCConvToLLVM(function.getCConv()));
1836  mapFunction(function.getName(), llvmFunc);
1837  addRuntimePreemptionSpecifier(function.getDsoLocal(), llvmFunc);
1838 
1839  // Convert function attributes.
1840  convertFunctionAttributes(function, llvmFunc);
1841 
1842  // Convert function kernel attributes to metadata.
1843  convertFunctionKernelAttributes(function, llvmFunc, *this);
1844 
1845  // Convert function_entry_count attribute to metadata.
1846  if (std::optional<uint64_t> entryCount = function.getFunctionEntryCount())
1847  llvmFunc->setEntryCount(entryCount.value());
1848 
1849  // Convert result attributes.
1850  if (ArrayAttr allResultAttrs = function.getAllResultAttrs()) {
1851  DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1852  FailureOr<llvm::AttrBuilder> attrBuilder =
1853  convertParameterAttrs(function, -1, resultAttrs);
1854  if (failed(attrBuilder))
1855  return failure();
1856  llvmFunc->addRetAttrs(*attrBuilder);
1857  }
1858 
1859  // Convert argument attributes.
1860  for (auto [argIdx, llvmArg] : llvm::enumerate(llvmFunc->args())) {
1861  if (DictionaryAttr argAttrs = function.getArgAttrDict(argIdx)) {
1862  FailureOr<llvm::AttrBuilder> attrBuilder =
1863  convertParameterAttrs(function, argIdx, argAttrs);
1864  if (failed(attrBuilder))
1865  return failure();
1866  llvmArg.addAttrs(*attrBuilder);
1867  }
1868  }
1869 
1870  // Forward the pass-through attributes to LLVM.
1871  FailureOr<llvm::AttrBuilder> convertedPassthroughAttrs =
1872  convertMLIRAttributesToLLVM(function.getLoc(), llvmFunc->getContext(),
1873  function.getPassthroughAttr(),
1874  function.getPassthroughAttrName());
1875  if (failed(convertedPassthroughAttrs))
1876  return failure();
1877  llvmFunc->addFnAttrs(*convertedPassthroughAttrs);
1878 
1879  // Convert visibility attribute.
1880  llvmFunc->setVisibility(convertVisibilityToLLVM(function.getVisibility_()));
1881 
1882  // Convert the comdat attribute.
1883  if (std::optional<mlir::SymbolRefAttr> comdat = function.getComdat()) {
1884  auto selectorOp = cast<ComdatSelectorOp>(
1885  SymbolTable::lookupNearestSymbolFrom(function, *comdat));
1886  llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1887  }
1888 
1889  if (auto gc = function.getGarbageCollector())
1890  llvmFunc->setGC(gc->str());
1891 
1892  if (auto unnamedAddr = function.getUnnamedAddr())
1893  llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1894 
1895  if (auto alignment = function.getAlignment())
1896  llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1897 
1898  // Translate the debug information for this function.
1899  debugTranslation->translate(function, *llvmFunc);
1900  }
1901 
1902  return success();
1903 }
1904 
1905 LogicalResult ModuleTranslation::convertFunctions() {
1906  // Convert functions.
1907  for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1908  // Do not convert external functions, but do process dialect attributes
1909  // attached to them.
1910  if (function.isExternal()) {
1911  if (failed(convertDialectAttributes(function, {})))
1912  return failure();
1913  continue;
1914  }
1915 
1916  if (failed(convertOneFunction(function)))
1917  return failure();
1918  }
1919 
1920  return success();
1921 }
1922 
1923 LogicalResult ModuleTranslation::convertIFuncs() {
1924  for (auto op : getModuleBody(mlirModule).getOps<IFuncOp>()) {
1925  llvm::Type *type = convertType(op.getIFuncType());
1926  llvm::GlobalValue::LinkageTypes linkage =
1927  convertLinkageToLLVM(op.getLinkage());
1928  llvm::Constant *resolver;
1929  if (auto *resolverFn = lookupFunction(op.getResolver())) {
1930  resolver = cast<llvm::Constant>(resolverFn);
1931  } else {
1933  op.getResolverAttr());
1934  resolver = cast<llvm::Constant>(lookupAlias(aliasOp));
1935  }
1936 
1937  auto *ifunc =
1938  llvm::GlobalIFunc::create(type, op.getAddressSpace(), linkage,
1939  op.getSymName(), resolver, llvmModule.get());
1940  addRuntimePreemptionSpecifier(op.getDsoLocal(), ifunc);
1941  ifunc->setUnnamedAddr(convertUnnamedAddrToLLVM(op.getUnnamedAddr()));
1942  ifunc->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1943 
1944  ifuncMapping.try_emplace(op, ifunc);
1945  }
1946 
1947  return success();
1948 }
1949 
1950 LogicalResult ModuleTranslation::convertComdats() {
1951  for (auto comdatOp : getModuleBody(mlirModule).getOps<ComdatOp>()) {
1952  for (auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1953  llvm::Module *module = getLLVMModule();
1954  if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1955  return emitError(selectorOp.getLoc())
1956  << "comdat selection symbols must be unique even in different "
1957  "comdat regions";
1958  llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1959  comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1960  comdatMapping.try_emplace(selectorOp, comdat);
1961  }
1962  }
1963  return success();
1964 }
1965 
1966 LogicalResult ModuleTranslation::convertUnresolvedBlockAddress() {
1967  for (auto &[blockAddressOp, llvmCst] : unresolvedBlockAddressMapping) {
1968  BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
1969  llvm::BasicBlock *llvmBlock = lookupBlockAddress(blockAddressAttr);
1970  assert(llvmBlock && "expected LLVM blocks to be already translated");
1971 
1972  // Update mapping with new block address constant.
1973  auto *llvmBlockAddr = llvm::BlockAddress::get(
1974  lookupFunction(blockAddressAttr.getFunction().getValue()), llvmBlock);
1975  llvmCst->replaceAllUsesWith(llvmBlockAddr);
1976  assert(llvmCst->use_empty() && "expected all uses to be replaced");
1977  cast<llvm::GlobalVariable>(llvmCst)->eraseFromParent();
1978  }
1979  unresolvedBlockAddressMapping.clear();
1980  return success();
1981 }
1982 
1983 void ModuleTranslation::setAccessGroupsMetadata(AccessGroupOpInterface op,
1984  llvm::Instruction *inst) {
1985  if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1986  inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1987 }
1988 
1989 llvm::MDNode *
1990 ModuleTranslation::getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr) {
1991  auto [scopeIt, scopeInserted] =
1992  aliasScopeMetadataMapping.try_emplace(aliasScopeAttr, nullptr);
1993  if (!scopeInserted)
1994  return scopeIt->second;
1995  llvm::LLVMContext &ctx = llvmModule->getContext();
1996  auto dummy = llvm::MDNode::getTemporary(ctx, {});
1997  // Convert the domain metadata node if necessary.
1998  auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
1999  aliasScopeAttr.getDomain(), nullptr);
2000  if (insertedDomain) {
2002  // Placeholder for potential self-reference.
2003  operands.push_back(dummy.get());
2004  if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
2005  operands.push_back(llvm::MDString::get(ctx, description));
2006  domainIt->second = llvm::MDNode::get(ctx, operands);
2007  // Self-reference for uniqueness.
2008  llvm::Metadata *replacement;
2009  if (auto stringAttr =
2010  dyn_cast<StringAttr>(aliasScopeAttr.getDomain().getId()))
2011  replacement = llvm::MDString::get(ctx, stringAttr.getValue());
2012  else
2013  replacement = domainIt->second;
2014  domainIt->second->replaceOperandWith(0, replacement);
2015  }
2016  // Convert the scope metadata node.
2017  assert(domainIt->second && "Scope's domain should already be valid");
2019  // Placeholder for potential self-reference.
2020  operands.push_back(dummy.get());
2021  operands.push_back(domainIt->second);
2022  if (StringAttr description = aliasScopeAttr.getDescription())
2023  operands.push_back(llvm::MDString::get(ctx, description));
2024  scopeIt->second = llvm::MDNode::get(ctx, operands);
2025  // Self-reference for uniqueness.
2026  llvm::Metadata *replacement;
2027  if (auto stringAttr = dyn_cast<StringAttr>(aliasScopeAttr.getId()))
2028  replacement = llvm::MDString::get(ctx, stringAttr.getValue());
2029  else
2030  replacement = scopeIt->second;
2031  scopeIt->second->replaceOperandWith(0, replacement);
2032  return scopeIt->second;
2033 }
2034 
2036  ArrayRef<AliasScopeAttr> aliasScopeAttrs) {
2038  nodes.reserve(aliasScopeAttrs.size());
2039  for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
2040  nodes.push_back(getOrCreateAliasScope(aliasScopeAttr));
2041  return llvm::MDNode::get(getLLVMContext(), nodes);
2042 }
2043 
2044 void ModuleTranslation::setAliasScopeMetadata(AliasAnalysisOpInterface op,
2045  llvm::Instruction *inst) {
2046  auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs, unsigned kind) {
2047  if (!aliasScopeAttrs || aliasScopeAttrs.empty())
2048  return;
2049  llvm::MDNode *node = getOrCreateAliasScopes(
2050  llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
2051  inst->setMetadata(kind, node);
2052  };
2053 
2054  populateScopeMetadata(op.getAliasScopesOrNull(),
2055  llvm::LLVMContext::MD_alias_scope);
2056  populateScopeMetadata(op.getNoAliasScopesOrNull(),
2057  llvm::LLVMContext::MD_noalias);
2058 }
2059 
2060 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr) const {
2061  return tbaaMetadataMapping.lookup(tbaaAttr);
2062 }
2063 
2064 void ModuleTranslation::setTBAAMetadata(AliasAnalysisOpInterface op,
2065  llvm::Instruction *inst) {
2066  ArrayAttr tagRefs = op.getTBAATagsOrNull();
2067  if (!tagRefs || tagRefs.empty())
2068  return;
2069 
2070  // LLVM IR currently does not support attaching more than one TBAA access tag
2071  // to a memory accessing instruction. It may be useful to support this in
2072  // future, but for the time being just ignore the metadata if MLIR operation
2073  // has multiple access tags.
2074  if (tagRefs.size() > 1) {
2075  op.emitWarning() << "TBAA access tags were not translated, because LLVM "
2076  "IR only supports a single tag per instruction";
2077  return;
2078  }
2079 
2080  llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
2081  inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
2082 }
2083 
2085  DereferenceableOpInterface op, llvm::Instruction *inst) {
2086  DereferenceableAttr derefAttr = op.getDereferenceableOrNull();
2087  if (!derefAttr)
2088  return;
2089 
2090  llvm::MDNode *derefSizeNode = llvm::MDNode::get(
2091  getLLVMContext(),
2093  llvm::IntegerType::get(getLLVMContext(), 64), derefAttr.getBytes())));
2094  unsigned kindId = derefAttr.getMayBeNull()
2095  ? llvm::LLVMContext::MD_dereferenceable_or_null
2096  : llvm::LLVMContext::MD_dereferenceable;
2097  inst->setMetadata(kindId, derefSizeNode);
2098 }
2099 
2100 void ModuleTranslation::setBranchWeightsMetadata(WeightedBranchOpInterface op) {
2101  SmallVector<uint32_t> weights;
2102  llvm::transform(op.getWeights(), std::back_inserter(weights),
2103  [](int32_t value) { return static_cast<uint32_t>(value); });
2104  if (weights.empty())
2105  return;
2106 
2107  llvm::Instruction *inst = isa<CallOp>(op) ? lookupCall(op) : lookupBranch(op);
2108  assert(inst && "expected the operation to have a mapping to an instruction");
2109  inst->setMetadata(
2110  llvm::LLVMContext::MD_prof,
2111  llvm::MDBuilder(getLLVMContext()).createBranchWeights(weights));
2112 }
2113 
2114 LogicalResult ModuleTranslation::createTBAAMetadata() {
2115  llvm::LLVMContext &ctx = llvmModule->getContext();
2116  llvm::IntegerType *offsetTy = llvm::IntegerType::get(ctx, 64);
2117 
2118  // Walk the entire module and create all metadata nodes for the TBAA
2119  // attributes. The code below relies on two invariants of the
2120  // `AttrTypeWalker`:
2121  // 1. Attributes are visited in post-order: Since the attributes create a DAG,
2122  // this ensures that any lookups into `tbaaMetadataMapping` for child
2123  // attributes succeed.
2124  // 2. Attributes are only ever visited once: This way we don't leak any
2125  // LLVM metadata instances.
2126  AttrTypeWalker walker;
2127  walker.addWalk([&](TBAARootAttr root) {
2128  tbaaMetadataMapping.insert(
2129  {root, llvm::MDNode::get(ctx, llvm::MDString::get(ctx, root.getId()))});
2130  });
2131 
2132  walker.addWalk([&](TBAATypeDescriptorAttr descriptor) {
2134  operands.push_back(llvm::MDString::get(ctx, descriptor.getId()));
2135  for (TBAAMemberAttr member : descriptor.getMembers()) {
2136  operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
2137  operands.push_back(llvm::ConstantAsMetadata::get(
2138  llvm::ConstantInt::get(offsetTy, member.getOffset())));
2139  }
2140 
2141  tbaaMetadataMapping.insert({descriptor, llvm::MDNode::get(ctx, operands)});
2142  });
2143 
2144  walker.addWalk([&](TBAATagAttr tag) {
2146 
2147  operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
2148  operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
2149 
2150  operands.push_back(llvm::ConstantAsMetadata::get(
2151  llvm::ConstantInt::get(offsetTy, tag.getOffset())));
2152  if (tag.getConstant())
2153  operands.push_back(
2155 
2156  tbaaMetadataMapping.insert({tag, llvm::MDNode::get(ctx, operands)});
2157  });
2158 
2159  mlirModule->walk([&](AliasAnalysisOpInterface analysisOpInterface) {
2160  if (auto attr = analysisOpInterface.getTBAATagsOrNull())
2161  walker.walk(attr);
2162  });
2163 
2164  return success();
2165 }
2166 
2167 LogicalResult ModuleTranslation::createIdentMetadata() {
2168  if (auto attr = mlirModule->getAttrOfType<StringAttr>(
2169  LLVMDialect::getIdentAttrName())) {
2170  StringRef ident = attr;
2171  llvm::LLVMContext &ctx = llvmModule->getContext();
2172  llvm::NamedMDNode *namedMd =
2173  llvmModule->getOrInsertNamedMetadata(LLVMDialect::getIdentAttrName());
2174  llvm::MDNode *md = llvm::MDNode::get(ctx, llvm::MDString::get(ctx, ident));
2175  namedMd->addOperand(md);
2176  }
2177 
2178  return success();
2179 }
2180 
2181 LogicalResult ModuleTranslation::createCommandlineMetadata() {
2182  if (auto attr = mlirModule->getAttrOfType<StringAttr>(
2183  LLVMDialect::getCommandlineAttrName())) {
2184  StringRef cmdLine = attr;
2185  llvm::LLVMContext &ctx = llvmModule->getContext();
2186  llvm::NamedMDNode *nmd = llvmModule->getOrInsertNamedMetadata(
2187  LLVMDialect::getCommandlineAttrName());
2188  llvm::MDNode *md =
2189  llvm::MDNode::get(ctx, llvm::MDString::get(ctx, cmdLine));
2190  nmd->addOperand(md);
2191  }
2192 
2193  return success();
2194 }
2195 
2196 LogicalResult ModuleTranslation::createDependentLibrariesMetadata() {
2197  if (auto dependentLibrariesAttr = mlirModule->getDiscardableAttr(
2198  LLVM::LLVMDialect::getDependentLibrariesAttrName())) {
2199  auto *nmd =
2200  llvmModule->getOrInsertNamedMetadata("llvm.dependent-libraries");
2201  llvm::LLVMContext &ctx = llvmModule->getContext();
2202  for (auto libAttr :
2203  cast<ArrayAttr>(dependentLibrariesAttr).getAsRange<StringAttr>()) {
2204  auto *md =
2205  llvm::MDNode::get(ctx, llvm::MDString::get(ctx, libAttr.getValue()));
2206  nmd->addOperand(md);
2207  }
2208  }
2209  return success();
2210 }
2211 
2213  llvm::Instruction *inst) {
2214  LoopAnnotationAttr attr =
2216  .Case<LLVM::BrOp, LLVM::CondBrOp>(
2217  [](auto branchOp) { return branchOp.getLoopAnnotationAttr(); });
2218  if (!attr)
2219  return;
2220  llvm::MDNode *loopMD =
2221  loopAnnotationTranslation->translateLoopAnnotation(attr, op);
2222  inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
2223 }
2224 
2225 void ModuleTranslation::setDisjointFlag(Operation *op, llvm::Value *value) {
2226  auto iface = cast<DisjointFlagInterface>(op);
2227  // We do a dyn_cast here in case the value got folded into a constant.
2228  if (auto disjointInst = dyn_cast<llvm::PossiblyDisjointInst>(value))
2229  disjointInst->setIsDisjoint(iface.getIsDisjoint());
2230 }
2231 
2233  return typeTranslator.translateType(type);
2234 }
2235 
2236 /// A helper to look up remapped operands in the value remapping table.
2238  SmallVector<llvm::Value *> remapped;
2239  remapped.reserve(values.size());
2240  for (Value v : values)
2241  remapped.push_back(lookupValue(v));
2242  return remapped;
2243 }
2244 
2245 llvm::OpenMPIRBuilder *ModuleTranslation::getOpenMPBuilder() {
2246  if (!ompBuilder) {
2247  ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
2248 
2249  // Flags represented as top-level OpenMP dialect attributes are set in
2250  // `OpenMPDialectLLVMIRTranslationInterface::amendOperation()`. Here we set
2251  // the default configuration.
2252  llvm::OpenMPIRBuilderConfig config(
2253  /* IsTargetDevice = */ false, /* IsGPU = */ false,
2254  /* OpenMPOffloadMandatory = */ false,
2255  /* HasRequiresReverseOffload = */ false,
2256  /* HasRequiresUnifiedAddress = */ false,
2257  /* HasRequiresUnifiedSharedMemory = */ false,
2258  /* HasRequiresDynamicAllocators = */ false);
2259  unsigned int defaultAS =
2260  getLLVMModule()->getDataLayout().getProgramAddressSpace();
2261  config.setDefaultTargetAS(defaultAS);
2262  ompBuilder->setConfig(std::move(config));
2263  ompBuilder->initialize();
2264  }
2265  return ompBuilder.get();
2266 }
2267 
2269  llvm::DILocalScope *scope) {
2270  return debugTranslation->translateLoc(loc, scope);
2271 }
2272 
2273 llvm::DIExpression *
2274 ModuleTranslation::translateExpression(LLVM::DIExpressionAttr attr) {
2275  return debugTranslation->translateExpression(attr);
2276 }
2277 
2278 llvm::DIGlobalVariableExpression *
2280  LLVM::DIGlobalVariableExpressionAttr attr) {
2281  return debugTranslation->translateGlobalVariableExpression(attr);
2282 }
2283 
2285  return debugTranslation->translate(attr);
2286 }
2287 
2288 llvm::RoundingMode
2289 ModuleTranslation::translateRoundingMode(LLVM::RoundingMode rounding) {
2290  return convertRoundingModeToLLVM(rounding);
2291 }
2292 
2294  LLVM::FPExceptionBehavior exceptionBehavior) {
2295  return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
2296 }
2297 
2298 llvm::NamedMDNode *
2300  return llvmModule->getOrInsertNamedMetadata(name);
2301 }
2302 
2303 static std::unique_ptr<llvm::Module>
2304 prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
2305  StringRef name) {
2306  m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
2307  auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
2308  if (auto dataLayoutAttr =
2309  m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
2310  llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
2311  } else {
2312  FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(""));
2313  if (auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
2314  if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
2315  llvmDataLayout =
2316  translateDataLayout(spec, DataLayout(iface), m->getLoc());
2317  }
2318  } else if (auto mod = dyn_cast<ModuleOp>(m)) {
2319  if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
2320  llvmDataLayout =
2321  translateDataLayout(spec, DataLayout(mod), m->getLoc());
2322  }
2323  }
2324  if (failed(llvmDataLayout))
2325  return nullptr;
2326  llvmModule->setDataLayout(*llvmDataLayout);
2327  }
2328  if (auto targetTripleAttr =
2329  m->getDiscardableAttr(LLVM::LLVMDialect::getTargetTripleAttrName()))
2330  llvmModule->setTargetTriple(
2331  llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
2332 
2333  if (auto asmAttr = m->getDiscardableAttr(
2334  LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
2335  auto asmArrayAttr = dyn_cast<ArrayAttr>(asmAttr);
2336  if (!asmArrayAttr) {
2337  m->emitError("expected an array attribute for a module level asm");
2338  return nullptr;
2339  }
2340 
2341  for (Attribute elt : asmArrayAttr) {
2342  auto asmStrAttr = dyn_cast<StringAttr>(elt);
2343  if (!asmStrAttr) {
2344  m->emitError(
2345  "expected a string attribute for each entry of a module level asm");
2346  return nullptr;
2347  }
2348  llvmModule->appendModuleInlineAsm(asmStrAttr.getValue());
2349  }
2350  }
2351 
2352  return llvmModule;
2353 }
2354 
2355 std::unique_ptr<llvm::Module>
2356 mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
2357  StringRef name, bool disableVerification) {
2358  if (!satisfiesLLVMModule(module)) {
2359  module->emitOpError("can not be translated to an LLVMIR module");
2360  return nullptr;
2361  }
2362 
2363  std::unique_ptr<llvm::Module> llvmModule =
2364  prepareLLVMModule(module, llvmContext, name);
2365  if (!llvmModule)
2366  return nullptr;
2367 
2370 
2371  ModuleTranslation translator(module, std::move(llvmModule));
2372  llvm::IRBuilder<llvm::TargetFolder> llvmBuilder(
2373  llvmContext,
2374  llvm::TargetFolder(translator.getLLVMModule()->getDataLayout()));
2375 
2376  // Convert module before functions and operations inside, so dialect
2377  // attributes can be used to change dialect-specific global configurations via
2378  // `amendOperation()`. These configurations can then influence the translation
2379  // of operations afterwards.
2380  if (failed(translator.convertOperation(*module, llvmBuilder)))
2381  return nullptr;
2382 
2383  if (failed(translator.convertComdats()))
2384  return nullptr;
2385  if (failed(translator.convertFunctionSignatures()))
2386  return nullptr;
2387  if (failed(translator.convertGlobalsAndAliases()))
2388  return nullptr;
2389  if (failed(translator.convertIFuncs()))
2390  return nullptr;
2391  if (failed(translator.createTBAAMetadata()))
2392  return nullptr;
2393  if (failed(translator.createIdentMetadata()))
2394  return nullptr;
2395  if (failed(translator.createCommandlineMetadata()))
2396  return nullptr;
2397  if (failed(translator.createDependentLibrariesMetadata()))
2398  return nullptr;
2399 
2400  // Convert other top-level operations if possible.
2401  for (Operation &o : getModuleBody(module).getOperations()) {
2402  if (!isa<LLVM::LLVMFuncOp, LLVM::AliasOp, LLVM::GlobalOp,
2403  LLVM::GlobalCtorsOp, LLVM::GlobalDtorsOp, LLVM::ComdatOp,
2404  LLVM::IFuncOp>(&o) &&
2405  !o.hasTrait<OpTrait::IsTerminator>() &&
2406  failed(translator.convertOperation(o, llvmBuilder))) {
2407  return nullptr;
2408  }
2409  }
2410 
2411  // Operations in function bodies with symbolic references must be converted
2412  // after the top-level operations they refer to are declared, so we do it
2413  // last.
2414  if (failed(translator.convertFunctions()))
2415  return nullptr;
2416 
2417  // Now that all MLIR blocks are resolved into LLVM ones, patch block address
2418  // constants to point to the correct blocks.
2419  if (failed(translator.convertUnresolvedBlockAddress()))
2420  return nullptr;
2421 
2422  // Add the necessary debug info module flags, if they were not encoded in MLIR
2423  // beforehand.
2424  translator.debugTranslation->addModuleFlagsIfNotPresent();
2425 
2426  // Call the OpenMP IR Builder callbacks prior to verifying the module
2427  if (auto *ompBuilder = translator.getOpenMPBuilder())
2428  ompBuilder->finalize();
2429 
2430  if (!disableVerification &&
2431  llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
2432  return nullptr;
2433 
2434  return std::move(translator.llvmModule);
2435 }
static MLIRContext * getContext(OpFoldResult val)
union mlir::linalg::@1252::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:29
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:186
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:268
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:673
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:809
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:561
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
const FrozenRewritePatternSet GreedyRewriteConfig config
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...