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