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/Frontend/OpenMP/OMPIRBuilder.h"
40#include "llvm/IR/BasicBlock.h"
41#include "llvm/IR/CFG.h"
42#include "llvm/IR/Constants.h"
43#include "llvm/IR/DerivedTypes.h"
44#include "llvm/IR/IRBuilder.h"
45#include "llvm/IR/InlineAsm.h"
46#include "llvm/IR/LLVMContext.h"
47#include "llvm/IR/MDBuilder.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 }
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 if (ompBuilder && !ompBuilder->isFinalized())
806 ompBuilder->finalize();
807}
808
810 SmallVector<Region *> toProcess;
811 toProcess.push_back(&region);
812 while (!toProcess.empty()) {
813 Region *current = toProcess.pop_back_val();
814 for (Block &block : *current) {
815 blockMapping.erase(&block);
816 for (Value arg : block.getArguments())
817 valueMapping.erase(arg);
818 for (Operation &op : block) {
819 for (Value value : op.getResults())
820 valueMapping.erase(value);
821 if (op.hasSuccessors())
822 branchMapping.erase(&op);
823 if (isa<LLVM::GlobalOp>(op))
824 globalsMapping.erase(&op);
825 if (isa<LLVM::AliasOp>(op))
826 aliasesMapping.erase(&op);
827 if (isa<LLVM::IFuncOp>(op))
828 ifuncMapping.erase(&op);
829 if (isa<LLVM::CallOp>(op))
830 callMapping.erase(&op);
831 llvm::append_range(
832 toProcess,
833 llvm::map_range(op.getRegions(), [](Region &r) { return &r; }));
834 }
835 }
836 }
837}
838
839/// Get the SSA value passed to the current block from the terminator operation
840/// of its predecessor.
841static Value getPHISourceValue(Block *current, Block *pred,
842 unsigned numArguments, unsigned index) {
843 Operation &terminator = *pred->getTerminator();
844 if (isa<LLVM::BrOp>(terminator))
845 return terminator.getOperand(index);
846
847#ifndef NDEBUG
848 llvm::SmallPtrSet<Block *, 4> seenSuccessors;
849 for (unsigned i = 0, e = terminator.getNumSuccessors(); i < e; ++i) {
850 Block *successor = terminator.getSuccessor(i);
851 auto branch = cast<BranchOpInterface>(terminator);
852 SuccessorOperands successorOperands = branch.getSuccessorOperands(i);
853 assert(
854 (!seenSuccessors.contains(successor) || successorOperands.empty()) &&
855 "successors with arguments in LLVM branches must be different blocks");
856 seenSuccessors.insert(successor);
857 }
858#endif
859
860 // For instructions that branch based on a condition value, we need to take
861 // the operands for the branch that was taken.
862 if (auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
863 // For conditional branches, we take the operands from either the "true" or
864 // the "false" branch.
865 return condBranchOp.getSuccessor(0) == current
866 ? condBranchOp.getTrueDestOperands()[index]
867 : condBranchOp.getFalseDestOperands()[index];
868 }
869
870 if (auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
871 // For switches, we take the operands from either the default case, or from
872 // the case branch that was taken.
873 if (switchOp.getDefaultDestination() == current)
874 return switchOp.getDefaultOperands()[index];
875 for (const auto &i : llvm::enumerate(switchOp.getCaseDestinations()))
876 if (i.value() == current)
877 return switchOp.getCaseOperands(i.index())[index];
878 }
879
880 if (auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(terminator)) {
881 // For indirect branches we take operands for each successor.
882 for (const auto &i : llvm::enumerate(indBrOp->getSuccessors())) {
883 if (indBrOp->getSuccessor(i.index()) == current)
884 return indBrOp.getSuccessorOperands(i.index())[index];
885 }
886 }
887
888 if (auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
889 return invokeOp.getNormalDest() == current
890 ? invokeOp.getNormalDestOperands()[index]
891 : invokeOp.getUnwindDestOperands()[index];
892 }
893
894 llvm_unreachable(
895 "only branch, switch or invoke operations can be terminators "
896 "of a block that has successors");
897}
898
899/// Connect the PHI nodes to the results of preceding blocks.
901 const ModuleTranslation &state) {
902 // Skip the first block, it cannot be branched to and its arguments correspond
903 // to the arguments of the LLVM function.
904 for (Block &bb : llvm::drop_begin(region)) {
905 llvm::BasicBlock *llvmBB = state.lookupBlock(&bb);
906 auto phis = llvmBB->phis();
907 auto numArguments = bb.getNumArguments();
908 assert(numArguments == std::distance(phis.begin(), phis.end()));
909 for (auto [index, phiNode] : llvm::enumerate(phis)) {
910 for (auto *pred : bb.getPredecessors()) {
911 // Find the LLVM IR block that contains the converted terminator
912 // instruction and use it in the PHI node. Note that this block is not
913 // necessarily the same as state.lookupBlock(pred), some operations
914 // (in particular, OpenMP operations using OpenMPIRBuilder) may have
915 // split the blocks.
916 llvm::Instruction *terminator =
917 state.lookupBranch(pred->getTerminator());
918 assert(terminator && "missing the mapping for a terminator");
919 phiNode.addIncoming(state.lookupValue(getPHISourceValue(
920 &bb, pred, numArguments, index)),
921 terminator->getParent());
922 }
923 }
924 }
925}
926
928 llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic,
930 return builder.CreateIntrinsicWithoutFolding(intrinsic, tys, args);
931}
932
934 llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic,
935 llvm::Type *retTy, ArrayRef<llvm::Value *> args) {
936 return builder.CreateIntrinsicWithoutFolding(retTy, intrinsic, args);
937}
938
940 llvm::IRBuilderBase &builder, ModuleTranslation &moduleTranslation,
941 Operation *intrOp, llvm::Intrinsic::ID intrinsic, unsigned numResults,
942 ArrayRef<unsigned> overloadedResults, ArrayRef<unsigned> overloadedOperands,
943 ArrayRef<unsigned> immArgPositions,
944 ArrayRef<StringLiteral> immArgAttrNames) {
945 assert(immArgPositions.size() == immArgAttrNames.size() &&
946 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
947 "length");
948
950 size_t numOpBundleOperands = 0;
951 auto opBundleSizesAttr = cast_if_present<DenseI32ArrayAttr>(
952 intrOp->getAttr(LLVMDialect::getOpBundleSizesAttrName()));
953 auto opBundleTagsAttr = cast_if_present<ArrayAttr>(
954 intrOp->getAttr(LLVMDialect::getOpBundleTagsAttrName()));
955
956 if (opBundleSizesAttr && opBundleTagsAttr) {
957 ArrayRef<int> opBundleSizes = opBundleSizesAttr.asArrayRef();
958 assert(opBundleSizes.size() == opBundleTagsAttr.size() &&
959 "operand bundles and tags do not match");
960
961 numOpBundleOperands = llvm::sum_of(opBundleSizes);
962 assert(numOpBundleOperands <= intrOp->getNumOperands() &&
963 "operand bundle operands is more than the number of operands");
964
965 ValueRange operands = intrOp->getOperands().take_back(numOpBundleOperands);
966 size_t nextOperandIdx = 0;
967 opBundles.reserve(opBundleSizesAttr.size());
968
969 for (auto [opBundleTagAttr, bundleSize] :
970 llvm::zip(opBundleTagsAttr, opBundleSizes)) {
971 auto bundleTag = cast<StringAttr>(opBundleTagAttr).str();
972 auto bundleOperands = moduleTranslation.lookupValues(
973 operands.slice(nextOperandIdx, bundleSize));
974 opBundles.emplace_back(std::move(bundleTag), std::move(bundleOperands));
975 nextOperandIdx += bundleSize;
976 }
977 }
978
979 // Map operands and attributes to LLVM values.
980 auto opOperands = intrOp->getOperands().drop_back(numOpBundleOperands);
981 auto operands = moduleTranslation.lookupValues(opOperands);
982 SmallVector<llvm::Value *> args(immArgPositions.size() + operands.size());
983 for (auto [immArgPos, immArgName] :
984 llvm::zip(immArgPositions, immArgAttrNames)) {
985 Attribute attr = intrOp->getAttr(immArgName);
986 if (auto intrinsicIntegerAttr =
987 dyn_cast<LLVM::IntrinsicIntegerAttrInterface>(attr))
988 attr = intrinsicIntegerAttr.getIntegerAttr();
989 auto typedAttr = llvm::cast<TypedAttr>(attr);
990 assert(typedAttr.getType().isIntOrFloat() &&
991 "expected int or float immarg");
992 auto *type = moduleTranslation.convertType(typedAttr.getType());
993 args[immArgPos] = LLVM::detail::getLLVMConstant(
994 type, typedAttr, intrOp->getLoc(), moduleTranslation);
995 }
996 unsigned opArg = 0;
997 for (auto &arg : args) {
998 if (!arg)
999 arg = operands[opArg++];
1000 }
1001
1002 // Resolve overloaded intrinsic declaration.
1003 SmallVector<llvm::Type *> overloadedTypes;
1004 for (unsigned overloadedResultIdx : overloadedResults) {
1005 if (numResults > 1) {
1006 // More than one result is mapped to an LLVM struct.
1007 overloadedTypes.push_back(moduleTranslation.convertType(
1008 llvm::cast<LLVM::LLVMStructType>(intrOp->getResult(0).getType())
1009 .getBody()[overloadedResultIdx]));
1010 } else {
1011 overloadedTypes.push_back(
1012 moduleTranslation.convertType(intrOp->getResult(0).getType()));
1013 }
1014 }
1015 for (unsigned overloadedOperandIdx : overloadedOperands)
1016 overloadedTypes.push_back(args[overloadedOperandIdx]->getType());
1017 llvm::Module *module = builder.GetInsertBlock()->getModule();
1018 llvm::Function *llvmIntr = llvm::Intrinsic::getOrInsertDeclaration(
1019 module, intrinsic, overloadedTypes);
1020
1021 return builder.CreateCall(llvmIntr, args, opBundles);
1022}
1023
1024/// Given a single MLIR operation, create the corresponding LLVM IR operation
1025/// using the `builder`.
1026LogicalResult ModuleTranslation::convertOperationImpl(
1027 Operation &op, llvm::IRBuilderBase &builder, bool recordInsertions) {
1028 const LLVMTranslationDialectInterface *opIface = iface.getInterfaceFor(&op);
1029 if (!opIface)
1030 return op.emitError("cannot be converted to LLVM IR: missing "
1031 "`LLVMTranslationDialectInterface` registration for "
1032 "dialect for op: ")
1033 << op.getName();
1034
1035 InstructionCapturingInserter::CollectionScope scope(builder,
1036 recordInsertions);
1037 if (failed(opIface->convertOperation(&op, builder, *this)))
1038 return op.emitError("LLVM Translation failed for operation: ")
1039 << op.getName();
1040
1041 return convertDialectAttributes(&op, scope.getCapturedInstructions());
1042}
1043
1044/// Convert block to LLVM IR. Unless `ignoreArguments` is set, emit PHI nodes
1045/// to define values corresponding to the MLIR block arguments. These nodes
1046/// are not connected to the source basic blocks, which may not exist yet. Uses
1047/// `builder` to construct the LLVM IR. Expects the LLVM IR basic block to have
1048/// been created for `bb` and included in the block mapping. Inserts new
1049/// instructions at the end of the block and leaves `builder` in a state
1050/// suitable for further insertion into the end of the block.
1051LogicalResult ModuleTranslation::convertBlockImpl(Block &bb,
1052 bool ignoreArguments,
1053 llvm::IRBuilderBase &builder,
1054 bool recordInsertions) {
1055 builder.SetInsertPoint(lookupBlock(&bb));
1056 auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
1057
1058 // Before traversing operations, make block arguments available through
1059 // value remapping and PHI nodes, but do not add incoming edges for the PHI
1060 // nodes just yet: those values may be defined by this or following blocks.
1061 // This step is omitted if "ignoreArguments" is set. The arguments of the
1062 // first block have been already made available through the remapping of
1063 // LLVM function arguments.
1064 if (!ignoreArguments) {
1065 auto predecessors = bb.getPredecessors();
1066 unsigned numPredecessors =
1067 std::distance(predecessors.begin(), predecessors.end());
1068 for (auto arg : bb.getArguments()) {
1069 auto wrappedType = arg.getType();
1070 if (!isCompatibleType(wrappedType))
1071 return emitError(bb.front().getLoc(),
1072 "block argument does not have an LLVM type");
1073 builder.SetCurrentDebugLocation(
1074 debugTranslation->translateLoc(arg.getLoc(), subprogram));
1075 llvm::Type *type = convertType(wrappedType);
1076 llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
1077 mapValue(arg, phi);
1078 }
1079 }
1080
1081 // Traverse operations.
1082 for (auto &op : bb) {
1083 // Set the current debug location within the builder.
1084 builder.SetCurrentDebugLocation(
1085 debugTranslation->translateLoc(op.getLoc(), subprogram));
1086
1087 if (failed(convertOperationImpl(op, builder, recordInsertions)))
1088 return failure();
1089
1090 // Set the branch weight metadata on the translated instruction.
1091 if (auto iface = dyn_cast<WeightedBranchOpInterface>(op))
1093 }
1094
1095 return success();
1096}
1097
1098/// A helper method to get the single Block in an operation honoring LLVM's
1099/// module requirements.
1101 return module->getRegion(0).front();
1102}
1103
1104/// A helper method to decide if a constant must not be set as a global variable
1105/// initializer. For an external linkage variable, the variable with an
1106/// initializer is considered externally visible and defined in this module, the
1107/// variable without an initializer is externally available and is defined
1108/// elsewhere.
1109static bool shouldDropGlobalInitializer(llvm::GlobalValue::LinkageTypes linkage,
1110 llvm::Constant *cst) {
1111 return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
1112 linkage == llvm::GlobalVariable::ExternalWeakLinkage;
1113}
1114
1115/// Sets the runtime preemption specifier of `gv` to dso_local if
1116/// `dsoLocalRequested` is true, otherwise it is left unchanged.
1117static void addRuntimePreemptionSpecifier(bool dsoLocalRequested,
1118 llvm::GlobalValue *gv) {
1119 if (dsoLocalRequested)
1120 gv->setDSOLocal(true);
1121}
1122
1123/// Attempts to translate an MLIR attribute identified by `key`, optionally with
1124/// the given `value`, into an LLVM IR attribute. Reports errors at `loc` if
1125/// any. If the attribute name corresponds to a known LLVM IR attribute kind,
1126/// creates the LLVM attribute of that kind; otherwise, keeps it as a string
1127/// attribute. Performs additional checks for attributes known to have or not
1128/// have a value in order to avoid assertions inside LLVM upon construction.
1129static FailureOr<llvm::Attribute>
1130convertMLIRAttributeToLLVM(Location loc, llvm::LLVMContext &ctx, StringRef key,
1131 StringRef value = StringRef()) {
1132 auto kind = llvm::Attribute::getAttrKindFromName(key);
1133 if (kind == llvm::Attribute::None)
1134 return llvm::Attribute::get(ctx, key, value);
1135
1136 if (llvm::Attribute::isIntAttrKind(kind)) {
1137 if (value.empty())
1138 return emitError(loc) << "LLVM attribute '" << key << "' expects a value";
1139
1141 if (!value.getAsInteger(/*Radix=*/0, result))
1142 return llvm::Attribute::get(ctx, kind, result);
1143 return llvm::Attribute::get(ctx, key, value);
1144 }
1145
1146 if (!value.empty())
1147 return emitError(loc) << "LLVM attribute '" << key
1148 << "' does not expect a value, found '" << value
1149 << "'";
1150
1151 return llvm::Attribute::get(ctx, kind);
1152}
1153
1154/// Converts the MLIR attributes listed in the given array attribute into LLVM
1155/// attributes. Returns an `AttrBuilder` containing the converted attributes.
1156/// Reports error to `loc` if any and returns immediately. Expects `arrayAttr`
1157/// to contain either string attributes, treated as value-less LLVM attributes,
1158/// or array attributes containing two string attributes, with the first string
1159/// being the name of the corresponding LLVM attribute and the second string
1160/// beings its value. Note that even integer attributes are expected to have
1161/// their values expressed as strings.
1162static FailureOr<llvm::AttrBuilder>
1163convertMLIRAttributesToLLVM(Location loc, llvm::LLVMContext &ctx,
1164 ArrayAttr arrayAttr, StringRef arrayAttrName) {
1165 llvm::AttrBuilder attrBuilder(ctx);
1166 if (!arrayAttr)
1167 return attrBuilder;
1168
1169 for (Attribute attr : arrayAttr) {
1170 if (auto stringAttr = dyn_cast<StringAttr>(attr)) {
1171 FailureOr<llvm::Attribute> llvmAttr =
1172 convertMLIRAttributeToLLVM(loc, ctx, stringAttr.getValue());
1173 if (failed(llvmAttr))
1174 return failure();
1175 attrBuilder.addAttribute(*llvmAttr);
1176 continue;
1177 }
1178
1179 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1180 if (!arrayAttr || arrayAttr.size() != 2)
1181 return emitError(loc) << "expected '" << arrayAttrName
1182 << "' to contain string or array attributes";
1183
1184 auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1185 auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1186 if (!keyAttr || !valueAttr)
1187 return emitError(loc) << "expected arrays within '" << arrayAttrName
1188 << "' to contain two strings";
1189
1190 FailureOr<llvm::Attribute> llvmAttr = convertMLIRAttributeToLLVM(
1191 loc, ctx, keyAttr.getValue(), valueAttr.getValue());
1192 if (failed(llvmAttr))
1193 return failure();
1194 attrBuilder.addAttribute(*llvmAttr);
1195 }
1196
1197 return attrBuilder;
1198}
1199
1200LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
1201 // Mapping from compile unit to its respective set of global variables.
1203 // Mapping from subprogram to its respective set of static local variables.
1205
1206 // First, create all global variables and global aliases in LLVM IR. A global
1207 // or alias body may refer to another global/alias or itself, so all the
1208 // mapping needs to happen prior to body conversion.
1209
1210 // Create all llvm::GlobalVariable
1211 for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1212 llvm::Type *type = convertType(op.getType());
1213 llvm::Constant *cst = nullptr;
1214 const bool deferValueAttrToPass2 = op.getValueOrNull() &&
1215 !op.getInitializerBlock() &&
1216 !isa<StringAttr>(op.getValueOrNull());
1217 if (op.getValueOrNull() && !deferValueAttrToPass2) {
1218 // String attributes are treated separately because they cannot appear as
1219 // in-function constants and are thus not supported by getLLVMConstant.
1220 if (auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1221 cst = llvm::ConstantDataArray::getString(
1222 llvmModule->getContext(), strAttr.getValue(), /*AddNull=*/false);
1223 type = cst->getType();
1224 }
1225 }
1226
1227 auto linkage = convertLinkageToLLVM(op.getLinkage());
1228
1229 // LLVM IR requires constant with linkage other than external or weak
1230 // external to have initializers. If MLIR does not provide an initializer,
1231 // default to undef.
1232 bool dropInitializer = shouldDropGlobalInitializer(linkage, cst);
1233 if (!deferValueAttrToPass2) {
1234 if (!dropInitializer && !cst)
1235 cst = llvm::UndefValue::get(type);
1236 else if (dropInitializer && cst)
1237 cst = nullptr;
1238 } else {
1239 cst = nullptr;
1240 }
1241
1242 auto *var = new llvm::GlobalVariable(
1243 *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1244 /*InsertBefore=*/nullptr, convertThreadLocalModeToLLVM(op.getTlsMode()),
1245 op.getAddrSpace(), op.getExternallyInitialized());
1246
1247 if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1248 auto selectorOp = cast<ComdatSelectorOp>(
1250 var->setComdat(comdatMapping.lookup(selectorOp));
1251 }
1252
1253 if (op.getUnnamedAddr().has_value())
1254 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1255
1256 if (op.getSection().has_value())
1257 var->setSection(*op.getSection());
1258
1259 addRuntimePreemptionSpecifier(op.getDsoLocal(), var);
1260
1261 std::optional<uint64_t> alignment = op.getAlignment();
1262 if (alignment.has_value())
1263 var->setAlignment(llvm::MaybeAlign(alignment.value()));
1264
1265 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1266
1267 globalsMapping.try_emplace(op, var);
1268 globalsByNameMapping.try_emplace(op.getSymName(), var);
1269
1270 // Add debug information if present.
1271 if (op.getDbgExprs()) {
1272 for (auto exprAttr :
1273 op.getDbgExprs()->getAsRange<DIGlobalVariableExpressionAttr>()) {
1274 llvm::DIGlobalVariableExpression *diGlobalExpr =
1275 debugTranslation->translateGlobalVariableExpression(exprAttr);
1276 llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1277 var->addDebugInfo(diGlobalExpr);
1278
1279 // There is no `globals` field in DICompileUnitAttr which can be
1280 // directly assigned to DICompileUnit. We have to build the list by
1281 // looking at the dbgExpr of all the GlobalOps. The scope of the
1282 // variable is used to get the DICompileUnit in which to add it. But
1283 // there are cases where the scope of a global does not directly point
1284 // to the DICompileUnit and we have to do a bit more work to get to
1285 // it. Some of those cases are:
1286 //
1287 // 1. For the languages that support modules, the scope hierarchy can
1288 // be variable -> DIModule -> DICompileUnit
1289 //
1290 // 2. For the Fortran common block variable, the scope hierarchy can
1291 // be variable -> DICommonBlock -> DISubprogram -> DICompileUnit
1292 //
1293 // 3. For entities like static local variables in C or variable with
1294 // SAVE attribute in Fortran, the scope hierarchy can be
1295 // variable (-> DILocalScope)* -> DISubprogram
1296 llvm::DIScope *scope = diGlobalVar->getScope();
1297 if (auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1298 scope = mod->getScope();
1299 else if (auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
1300 if (auto *sp =
1301 dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
1302 scope = sp->getUnit();
1303 } else if (auto *lbb =
1304 dyn_cast_if_present<llvm::DILexicalBlockBase>(scope)) {
1305 scope = lbb->getSubprogram();
1306 }
1307
1308 // Get the compile unit (scope) of the the global variable, or the
1309 // subprogram of the static local variable.
1310 if (llvm::DICompileUnit *compileUnit =
1311 dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1312 // Update the compile unit with this incoming global variable
1313 // expression during the finalizing step later.
1314 globalGVars[compileUnit].push_back(diGlobalExpr);
1315 } else if (llvm::DISubprogram *sp =
1316 dyn_cast_if_present<llvm::DISubprogram>(scope)) {
1317 // Update the subprogram with this incoming static local variable
1318 // expression during the finalizing step later.
1319 staticLocals[sp].push_back(diGlobalExpr);
1320 }
1321 }
1322 }
1323
1324 // Forward the target-specific attributes to LLVM.
1325 FailureOr<llvm::AttrBuilder> convertedTargetSpecificAttrs =
1327 op.getTargetSpecificAttrsAttr(),
1328 op.getTargetSpecificAttrsAttrName());
1329 if (failed(convertedTargetSpecificAttrs))
1330 return failure();
1331 var->addAttributes(*convertedTargetSpecificAttrs);
1332 }
1333
1334 // Value-attribute initializers may reference other globals by symbol name.
1335 // Register every global above before materializing those constants.
1336 for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1337 if (!op.getValueOrNull() || op.getInitializerBlock() ||
1338 isa<StringAttr>(op.getValueOrNull()))
1339 continue;
1340
1341 llvm::Type *type = convertType(op.getType());
1342 llvm::Constant *cst =
1343 getLLVMConstant(type, op.getValueOrNull(), op.getLoc(), *this);
1344 if (!cst)
1345 return failure();
1346
1347 auto linkage = convertLinkageToLLVM(op.getLinkage());
1348 bool dropInitializer = shouldDropGlobalInitializer(linkage, cst);
1349 auto *var = cast<llvm::GlobalVariable>(lookupGlobal(op));
1350 if (dropInitializer)
1351 var->setInitializer(nullptr);
1352 else
1353 var->setInitializer(cst);
1354 }
1355
1356 // Create all llvm::GlobalAlias
1357 for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1358 llvm::Type *type = convertType(op.getType());
1359 llvm::Constant *cst = nullptr;
1360 llvm::GlobalValue::LinkageTypes linkage =
1361 convertLinkageToLLVM(op.getLinkage());
1362 llvm::Module &llvmMod = *llvmModule;
1363
1364 // Note address space and aliasee info isn't set just yet.
1365 llvm::GlobalAlias *var = llvm::GlobalAlias::create(
1366 type, op.getAddrSpace(), linkage, op.getSymName(), /*placeholder*/ cst,
1367 &llvmMod);
1368
1369 var->setThreadLocalMode(convertThreadLocalModeToLLVM(op.getTlsMode()));
1370
1371 // Note there is no need to setup the comdat because GlobalAlias calls into
1372 // the aliasee comdat information automatically.
1373
1374 if (op.getUnnamedAddr().has_value())
1375 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1376
1377 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1378
1379 aliasesMapping.try_emplace(op, var);
1380 }
1381
1382 // Convert global variable bodies.
1383 for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1384 if (Block *initializer = op.getInitializerBlock()) {
1385 llvm::IRBuilder<llvm::TargetFolder> builder(
1386 llvmModule->getContext(),
1387 llvm::TargetFolder(llvmModule->getDataLayout()));
1388
1389 [[maybe_unused]] int numConstantsHit = 0;
1390 [[maybe_unused]] int numConstantsErased = 0;
1391 DenseMap<llvm::ConstantAggregate *, int> constantAggregateUseMap;
1392
1393 for (auto &op : initializer->without_terminator()) {
1394 if (failed(convertOperation(op, builder)))
1395 return emitError(op.getLoc(), "fail to convert global initializer");
1396 auto *cst = dyn_cast<llvm::Constant>(lookupValue(op.getResult(0)));
1397 if (!cst)
1398 return emitError(op.getLoc(), "unemittable constant value");
1399
1400 // When emitting an LLVM constant, a new constant is created and the old
1401 // constant may become dangling and take space. We should remove the
1402 // dangling constants to avoid memory explosion especially for constant
1403 // arrays whose number of elements is large.
1404 // Because multiple operations may refer to the same constant, we need
1405 // to count the number of uses of each constant array and remove it only
1406 // when the count becomes zero.
1407 if (auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1408 numConstantsHit++;
1409 Value result = op.getResult(0);
1410 int numUsers = std::distance(result.use_begin(), result.use_end());
1411 auto [iterator, inserted] =
1412 constantAggregateUseMap.try_emplace(agg, numUsers);
1413 if (!inserted) {
1414 // Key already exists, update the value
1415 iterator->second += numUsers;
1416 }
1417 }
1418 // Scan the operands of the operation to decrement the use count of
1419 // constants. Erase the constant if the use count becomes zero.
1420 for (Value v : op.getOperands()) {
1421 auto *cst = dyn_cast<llvm::ConstantAggregate>(lookupValue(v));
1422 if (!cst)
1423 continue;
1424 auto iter = constantAggregateUseMap.find(cst);
1425 assert(iter != constantAggregateUseMap.end() && "constant not found");
1426 iter->second--;
1427 if (iter->second == 0) {
1428 // NOTE: cannot call removeDeadConstantUsers() here because it
1429 // may remove the constant which has uses not be converted yet.
1430 if (cst->user_empty()) {
1431 cst->destroyConstant();
1432 numConstantsErased++;
1433 }
1434 constantAggregateUseMap.erase(iter);
1435 }
1436 }
1437 }
1438
1439 ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1440 llvm::Constant *cst =
1441 cast<llvm::Constant>(lookupValue(ret.getOperand(0)));
1442 auto *global = cast<llvm::GlobalVariable>(lookupGlobal(op));
1443 if (!shouldDropGlobalInitializer(global->getLinkage(), cst))
1444 global->setInitializer(cst);
1445
1446 // Try to remove the dangling constants again after all operations are
1447 // converted.
1448 for (auto it : constantAggregateUseMap) {
1449 auto *cst = it.first;
1450 cst->removeDeadConstantUsers();
1451 if (cst->user_empty()) {
1452 cst->destroyConstant();
1453 numConstantsErased++;
1454 }
1455 }
1456
1457 LLVM_DEBUG(llvm::dbgs()
1458 << "Convert initializer for " << op.getName() << "\n";
1459 llvm::dbgs() << numConstantsHit << " new constants hit\n";
1460 llvm::dbgs()
1461 << numConstantsErased << " dangling constants erased\n";);
1462 }
1463 }
1464
1465 // Convert llvm.mlir.global_ctors and dtors.
1466 for (Operation &op : getModuleBody(mlirModule)) {
1467 auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1468 auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1469 if (!ctorOp && !dtorOp)
1470 continue;
1471
1472 // The empty / zero initialized version of llvm.global_(c|d)tors cannot be
1473 // handled by appendGlobalFn logic below, which just ignores empty (c|d)tor
1474 // lists. Make sure it gets emitted.
1475 if ((ctorOp && ctorOp.getCtors().empty()) ||
1476 (dtorOp && dtorOp.getDtors().empty())) {
1477 llvm::IRBuilder<llvm::TargetFolder> builder(
1478 llvmModule->getContext(),
1479 llvm::TargetFolder(llvmModule->getDataLayout()));
1480 llvm::Type *eltTy = llvm::StructType::get(
1481 builder.getInt32Ty(), builder.getPtrTy(), builder.getPtrTy());
1482 llvm::ArrayType *at = llvm::ArrayType::get(eltTy, 0);
1483 llvm::Constant *zeroInit = llvm::Constant::getNullValue(at);
1484 (void)new llvm::GlobalVariable(
1485 *llvmModule, zeroInit->getType(), false,
1486 llvm::GlobalValue::AppendingLinkage, zeroInit,
1487 ctorOp ? "llvm.global_ctors" : "llvm.global_dtors");
1488 } else {
1489 auto range = ctorOp
1490 ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1491 : llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1492 auto appendGlobalFn =
1493 ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1494 for (const auto &[sym, prio] : range) {
1495 llvm::Function *f =
1496 lookupFunction(cast<FlatSymbolRefAttr>(sym).getValue());
1497 appendGlobalFn(*llvmModule, f, cast<IntegerAttr>(prio).getInt(),
1498 /*Data=*/nullptr);
1499 }
1500 }
1501 }
1502
1503 for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1504 if (failed(convertDialectAttributes(op, {})))
1505 return failure();
1506
1507 // Finally, update the compile units their respective sets of global variables
1508 // created earlier.
1509 for (const auto &[compileUnit, globals] : globalGVars)
1510 compileUnit->replaceGlobalVariables(
1511 llvm::MDTuple::get(getLLVMContext(), globals));
1512
1513 // And update the subprograms with their respective sets of static local
1514 // variables.
1515 for (const auto &[sp, globals] : staticLocals)
1516 sp->retainNodes(globals.begin(), globals.end());
1517
1518 // Convert global alias bodies.
1519 for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1520 Block &initializer = op.getInitializerBlock();
1521 llvm::IRBuilder<llvm::TargetFolder> builder(
1522 llvmModule->getContext(),
1523 llvm::TargetFolder(llvmModule->getDataLayout()));
1524
1525 for (mlir::Operation &op : initializer.without_terminator()) {
1526 if (failed(convertOperation(op, builder)))
1527 return emitError(op.getLoc(), "fail to convert alias initializer");
1528 if (!isa<llvm::Constant>(lookupValue(op.getResult(0))))
1529 return emitError(op.getLoc(), "unemittable constant value");
1530 }
1531
1532 auto ret = cast<ReturnOp>(initializer.getTerminator());
1533 auto *cst = cast<llvm::Constant>(lookupValue(ret.getOperand(0)));
1534 assert(aliasesMapping.count(op));
1535 auto *alias = cast<llvm::GlobalAlias>(aliasesMapping[op]);
1536 alias->setAliasee(cst);
1537 }
1538
1539 for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>())
1540 if (failed(convertDialectAttributes(op, {})))
1541 return failure();
1542
1543 return success();
1544}
1545
1546/// Return a representation of `value` as metadata.
1547static llvm::Metadata *convertIntegerToMetadata(llvm::LLVMContext &context,
1548 const llvm::APInt &value) {
1549 llvm::Constant *constant = llvm::ConstantInt::get(context, value);
1550 return llvm::ConstantAsMetadata::get(constant);
1551}
1552
1553/// Return a representation of `value` as an MDNode.
1554static llvm::MDNode *convertIntegerToMDNode(llvm::LLVMContext &context,
1555 const llvm::APInt &value) {
1556 return llvm::MDNode::get(context, convertIntegerToMetadata(context, value));
1557}
1558
1559/// Return an MDNode encoding `vec_type_hint` metadata.
1560static llvm::MDNode *convertVecTypeHintToMDNode(llvm::LLVMContext &context,
1561 llvm::Type *type,
1562 bool isSigned) {
1563 llvm::Metadata *typeMD =
1564 llvm::ConstantAsMetadata::get(llvm::UndefValue::get(type));
1565 llvm::Metadata *isSignedMD =
1566 convertIntegerToMetadata(context, llvm::APInt(32, isSigned ? 1 : 0));
1567 return llvm::MDNode::get(context, {typeMD, isSignedMD});
1568}
1569
1570/// Return an MDNode with a tuple given by the values in `values`.
1571static llvm::MDNode *convertIntegerArrayToMDNode(llvm::LLVMContext &context,
1572 ArrayRef<int32_t> values) {
1574 llvm::transform(
1575 values, std::back_inserter(mdValues), [&context](int32_t value) {
1576 return convertIntegerToMetadata(context, llvm::APInt(32, value));
1577 });
1578 return llvm::MDNode::get(context, mdValues);
1579}
1580
1581FailureOr<llvm::Metadata *> ModuleTranslation::convertMetadataAttr(
1583 llvm::LLVMContext &llvmContext = getLLVMContext();
1584
1586 .Case([&](MDStringAttr a) -> FailureOr<llvm::Metadata *> {
1587 return llvm::MDString::get(llvmContext, a.getValue().getValue());
1588 })
1589 .Case([&](MDConstantAttr a) -> FailureOr<llvm::Metadata *> {
1590 IntegerAttr intAttr = llvm::dyn_cast<IntegerAttr>(a.getValue());
1591 if (!intAttr) {
1592 return emitError()
1593 << "expected integer attribute in metadata constant";
1594 }
1595 return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
1596 llvm::Type::getIntNTy(llvmContext,
1597 intAttr.getType().getIntOrFloatBitWidth()),
1598 intAttr.getValue()));
1599 })
1600 .Case([&](MDGlobalValueAttr a) -> FailureOr<llvm::Metadata *> {
1601 if (llvm::Function *fn = lookupFunction(a.getName().getValue()))
1602 return llvm::ValueAsMetadata::get(fn);
1603 if (llvm::GlobalValue *global = lookupGlobal(a.getName().getValue()))
1604 return llvm::ValueAsMetadata::get(global);
1605 Operation *symbol =
1606 symbolTable().lookupSymbolIn(mlirModule, a.getName());
1607 if (auto alias = dyn_cast_if_present<LLVM::AliasOp>(symbol)) {
1608 if (llvm::GlobalValue *global = lookupAlias(alias))
1609 return llvm::ValueAsMetadata::get(global);
1610 }
1611 if (auto ifunc = dyn_cast_if_present<LLVM::IFuncOp>(symbol)) {
1612 if (llvm::GlobalValue *global = lookupIFunc(ifunc))
1613 return llvm::ValueAsMetadata::get(global);
1614 }
1615 return emitError() << "could not resolve metadata reference '"
1616 << a.getName() << "'";
1617 })
1618 .Case([&](MDNullAttr a) -> FailureOr<llvm::Metadata *> {
1619 return llvm::ConstantAsMetadata::get(llvm::ConstantPointerNull::get(
1620 llvm::PointerType::get(llvmContext, a.getAddressSpace())));
1621 })
1622 .Case([&](MDAddrSpaceCastAttr a) -> FailureOr<llvm::Metadata *> {
1623 FailureOr<llvm::Metadata *> arg =
1624 convertMetadataAttr(a.getArg(), emitError);
1625 if (failed(arg))
1626 return failure();
1627 // The verifier restricts the operand to pointer-valued metadata
1628 // attributes, all of which translate to a ConstantAsMetadata.
1629 auto *argAsMD = cast<llvm::ConstantAsMetadata>(*arg);
1630 return llvm::ConstantAsMetadata::get(
1631 llvm::ConstantExpr::getAddrSpaceCast(
1632 argAsMD->getValue(),
1633 llvm::PointerType::get(llvmContext, a.getAddressSpace())));
1634 })
1635 .Case([&](MDNodeAttr a) -> FailureOr<llvm::Metadata *> {
1637 for (Attribute operand : a.getOperands()) {
1638 FailureOr<llvm::Metadata *> md =
1640 if (failed(md))
1641 return failure();
1642 operands.push_back(*md);
1643 }
1644 return llvm::MDNode::get(llvmContext, operands);
1645 })
1646 .Default([&](Attribute attr) -> FailureOr<llvm::Metadata *> {
1647 return emitError() << "unsupported LLVM metadata attribute " << attr;
1648 });
1649}
1650
1651LogicalResult ModuleTranslation::convertFunctionMetadata() {
1652 for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1653 ArrayAttr metadata = function.getFunctionMetadataAttr();
1654 if (!metadata)
1655 continue;
1656
1657 llvm::Function *llvmFunc = lookupFunction(function.getName());
1658 for (auto entry : metadata.getAsRange<LLVM::FunctionMetadataAttr>()) {
1659 StringRef metadataName = entry.getMetadataName().getValue();
1660
1661 FailureOr<llvm::Metadata *> md =
1662 convertMetadataAttr(entry.getNode(), [&]() {
1663 return function.emitError()
1664 << "failed to convert function_metadata entry '"
1665 << metadataName << "': ";
1666 });
1667 if (failed(md))
1668 return failure();
1669 llvm::MDNode *node = llvm::dyn_cast_if_present<llvm::MDNode>(*md);
1670 if (!node) {
1671 return function.emitError()
1672 << "failed to convert function_metadata entry '" << metadataName
1673 << "'";
1674 }
1675 llvmFunc->addMetadata(metadataName, *node);
1676 }
1677 }
1678 return success();
1679}
1680
1681LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1682 // Clear the block, branch value mappings, they are only relevant within one
1683 // function.
1684 blockMapping.clear();
1685 valueMapping.clear();
1686 branchMapping.clear();
1687 llvm::Function *llvmFunc = lookupFunction(func.getName());
1688 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1689
1690 // Add function arguments to the value remapping table.
1691 for (auto [mlirArg, llvmArg] :
1692 llvm::zip(func.getArguments(), llvmFunc->args()))
1693 mapValue(mlirArg, &llvmArg);
1694
1695 // Check the personality and set it.
1696 if (func.getPersonality()) {
1697 llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1698 if (llvm::Constant *pfunc = getLLVMConstant(ty, func.getPersonalityAttr(),
1699 func.getLoc(), *this))
1700 llvmFunc->setPersonalityFn(pfunc);
1701 }
1702
1703 if (std::optional<StringRef> section = func.getSection())
1704 llvmFunc->setSection(*section);
1705
1706 if (func.getArmStreaming())
1707 llvmFunc->addFnAttr("aarch64_pstate_sm_enabled");
1708 else if (func.getArmLocallyStreaming())
1709 llvmFunc->addFnAttr("aarch64_pstate_sm_body");
1710 else if (func.getArmStreamingCompatible())
1711 llvmFunc->addFnAttr("aarch64_pstate_sm_compatible");
1712
1713 if (func.getArmNewZa())
1714 llvmFunc->addFnAttr("aarch64_new_za");
1715 else if (func.getArmInZa())
1716 llvmFunc->addFnAttr("aarch64_in_za");
1717 else if (func.getArmOutZa())
1718 llvmFunc->addFnAttr("aarch64_out_za");
1719 else if (func.getArmInoutZa())
1720 llvmFunc->addFnAttr("aarch64_inout_za");
1721 else if (func.getArmPreservesZa())
1722 llvmFunc->addFnAttr("aarch64_preserves_za");
1723
1724 if (auto targetCpu = func.getTargetCpu())
1725 llvmFunc->addFnAttr("target-cpu", *targetCpu);
1726
1727 if (auto tuneCpu = func.getTuneCpu())
1728 llvmFunc->addFnAttr("tune-cpu", *tuneCpu);
1729
1730 if (auto reciprocalEstimates = func.getReciprocalEstimates())
1731 llvmFunc->addFnAttr("reciprocal-estimates", *reciprocalEstimates);
1732
1733 if (auto preferVectorWidth = func.getPreferVectorWidth())
1734 llvmFunc->addFnAttr("prefer-vector-width", *preferVectorWidth);
1735
1736 if (func.getUseSampleProfile())
1737 llvmFunc->addFnAttr("use-sample-profile");
1738
1739 if (auto attr = func.getVscaleRange())
1740 llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1741 getLLVMContext(), attr->getMinRange().getInt(),
1742 attr->getMaxRange().getInt()));
1743
1744 if (auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1745 llvmFunc->addFnAttr("no-signed-zeros-fp-math",
1746 llvm::toStringRef(*noSignedZerosFpMath));
1747
1748 if (auto fpContract = func.getFpContract())
1749 llvmFunc->addFnAttr("fp-contract", *fpContract);
1750
1751 if (auto instrumentFunctionEntry = func.getInstrumentFunctionEntry())
1752 llvmFunc->addFnAttr("instrument-function-entry", *instrumentFunctionEntry);
1753
1754 if (auto instrumentFunctionExit = func.getInstrumentFunctionExit())
1755 llvmFunc->addFnAttr("instrument-function-exit", *instrumentFunctionExit);
1756
1757 // First, create all blocks so we can jump to them.
1758 for (auto &bb : func) {
1759 auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1760 llvmBB->insertInto(llvmFunc);
1761 mapBlock(&bb, llvmBB);
1762 }
1763
1764 // Then, convert blocks one by one in topological order to ensure defs are
1765 // converted before uses.
1766 auto blocks = getBlocksSortedByDominance(func.getBody());
1767 for (Block *bb : blocks) {
1768 CapturingIRBuilder builder(llvmContext,
1769 llvm::TargetFolder(llvmModule->getDataLayout()));
1770 if (failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1771 /*recordInsertions=*/true)))
1772 return failure();
1773 }
1774
1775 // After all blocks have been traversed and values mapped, connect the PHI
1776 // nodes to the results of preceding blocks.
1777 detail::connectPHINodes(func.getBody(), *this);
1778
1779 // Finally, convert dialect attributes attached to the function.
1780 return convertDialectAttributes(func, {});
1781}
1782
1783LogicalResult ModuleTranslation::convertDialectAttributes(
1784 Operation *op, ArrayRef<llvm::Instruction *> instructions) {
1785 for (NamedAttribute attribute : op->getDialectAttrs())
1786 if (failed(iface.amendOperation(op, instructions, attribute, *this)))
1787 return failure();
1788 return success();
1789}
1790
1791/// Converts memory effect attributes from `func` and attaches them to
1792/// `llvmFunc`.
1794 llvm::Function *llvmFunc) {
1795 if (!func.getMemoryEffects())
1796 return;
1797
1798 MemoryEffectsAttr memEffects = func.getMemoryEffectsAttr();
1799
1800 // Add memory effects incrementally.
1801 llvm::MemoryEffects newMemEffects =
1802 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1803 convertModRefInfoToLLVM(memEffects.getArgMem()));
1804 newMemEffects |= llvm::MemoryEffects(
1805 llvm::MemoryEffects::Location::InaccessibleMem,
1806 convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1807 newMemEffects |=
1808 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1809 convertModRefInfoToLLVM(memEffects.getOther()));
1810 newMemEffects |=
1811 llvm::MemoryEffects(llvm::MemoryEffects::Location::ErrnoMem,
1812 convertModRefInfoToLLVM(memEffects.getErrnoMem()));
1813 newMemEffects |=
1814 llvm::MemoryEffects(llvm::MemoryEffects::Location::TargetMem0,
1815 convertModRefInfoToLLVM(memEffects.getTargetMem0()));
1816 newMemEffects |=
1817 llvm::MemoryEffects(llvm::MemoryEffects::Location::TargetMem1,
1818 convertModRefInfoToLLVM(memEffects.getTargetMem1()));
1819 llvmFunc->setMemoryEffects(newMemEffects);
1820}
1821
1822llvm::Attribute
1824 if (!allocSizeAttr || allocSizeAttr.empty())
1825 return llvm::Attribute{};
1826
1827 unsigned elemSize = static_cast<unsigned>(allocSizeAttr[0]);
1828 std::optional<unsigned> numElems;
1829 if (allocSizeAttr.size() > 1)
1830 numElems = static_cast<unsigned>(allocSizeAttr[1]);
1831
1832 return llvm::Attribute::getWithAllocSizeArgs(getLLVMContext(), elemSize,
1833 numElems);
1834}
1836 llvm::AttrBuilder &Attrs) {
1837 std::optional<DenormalFPEnvAttr> denormalFpEnv = func.getDenormalFpenv();
1838 if (!denormalFpEnv)
1839 return;
1840
1841 llvm::DenormalMode DefaultMode(
1842 convertDenormalModeKindToLLVM(denormalFpEnv->getDefaultOutputMode()),
1843 convertDenormalModeKindToLLVM(denormalFpEnv->getDefaultInputMode()));
1844 llvm::DenormalMode FloatMode(
1845 convertDenormalModeKindToLLVM(denormalFpEnv->getFloatOutputMode()),
1846 convertDenormalModeKindToLLVM(denormalFpEnv->getFloatInputMode()));
1847
1848 llvm::DenormalFPEnv FPEnv(DefaultMode, FloatMode);
1849 Attrs.addDenormalFPEnvAttr(FPEnv);
1850}
1851
1852/// Converts function attributes from `func` and attaches them to `llvmFunc`.
1854 llvm::Function *llvmFunc) {
1855 // FIXME: Use AttrBuilder far all cases
1856 llvm::AttrBuilder AttrBuilder(llvmFunc->getContext());
1857
1858 if (func.getNoInlineAttr())
1859 llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1860 if (func.getAlwaysInlineAttr())
1861 llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1862 if (func.getInlineHintAttr())
1863 llvmFunc->addFnAttr(llvm::Attribute::InlineHint);
1864 if (func.getOptimizeNoneAttr())
1865 llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1866 if (func.getReturnsTwiceAttr())
1867 llvmFunc->addFnAttr(llvm::Attribute::ReturnsTwice);
1868 if (func.getColdAttr())
1869 llvmFunc->addFnAttr(llvm::Attribute::Cold);
1870 if (func.getHotAttr())
1871 llvmFunc->addFnAttr(llvm::Attribute::Hot);
1872 if (func.getNoduplicateAttr())
1873 llvmFunc->addFnAttr(llvm::Attribute::NoDuplicate);
1874 if (func.getConvergentAttr())
1875 llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1876 if (func.getNoUnwindAttr())
1877 llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1878 if (func.getWillReturnAttr())
1879 llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1880 if (func.getNoreturnAttr())
1881 llvmFunc->addFnAttr(llvm::Attribute::NoReturn);
1882 if (func.getOptsizeAttr())
1883 llvmFunc->addFnAttr(llvm::Attribute::OptimizeForSize);
1884 if (func.getMinsizeAttr())
1885 llvmFunc->addFnAttr(llvm::Attribute::MinSize);
1886 if (func.getSaveRegParamsAttr())
1887 llvmFunc->addFnAttr("save-reg-params");
1888 if (func.getNoCallerSavedRegistersAttr())
1889 llvmFunc->addFnAttr("no_caller_saved_registers");
1890 if (func.getNocallbackAttr())
1891 llvmFunc->addFnAttr(llvm::Attribute::NoCallback);
1892 if (StringAttr modFormat = func.getModularFormatAttr())
1893 llvmFunc->addFnAttr("modular-format", modFormat.getValue());
1894 if (TargetFeaturesAttr targetFeatAttr = func.getTargetFeaturesAttr())
1895 llvmFunc->addFnAttr("target-features", targetFeatAttr.getFeaturesString());
1896 if (FramePointerKindAttr fpAttr = func.getFramePointerAttr())
1897 llvmFunc->addFnAttr("frame-pointer", stringifyFramePointerKind(
1898 fpAttr.getFramePointerKind()));
1899 if (UWTableKindAttr uwTableKindAttr = func.getUwtableKindAttr())
1900 llvmFunc->setUWTableKind(
1901 convertUWTableKindToLLVM(uwTableKindAttr.getUwtableKind()));
1902 if (StringAttr zcsr = func.getZeroCallUsedRegsAttr())
1903 llvmFunc->addFnAttr("zero-call-used-regs", zcsr.getValue());
1904
1905 if (ArrayAttr noBuiltins = func.getNobuiltinsAttr()) {
1906 if (noBuiltins.empty())
1907 llvmFunc->addFnAttr("no-builtins");
1908
1909 mod.convertFunctionAttrCollection(noBuiltins, llvmFunc,
1911 }
1912
1913 mod.convertFunctionAttrCollection(func.getDefaultFuncAttrsAttr(), llvmFunc,
1915
1916 if (llvm::Attribute attr = mod.convertAllocsizeAttr(func.getAllocsizeAttr());
1917 attr.isValid())
1918 llvmFunc->addFnAttr(attr);
1919
1921
1922 convertDenormalFPEnvAttribute(func, AttrBuilder);
1923 llvmFunc->addFnAttrs(AttrBuilder);
1924}
1925
1926/// Converts function attributes from `func` and attaches them to `llvmFunc`.
1928 llvm::Function *llvmFunc,
1929 ModuleTranslation &translation) {
1930 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1931
1932 if (VecTypeHintAttr vecTypeHint = func.getVecTypeHintAttr()) {
1933 Type type = vecTypeHint.getHint().getValue();
1934 llvm::Type *llvmType = translation.convertType(type);
1935 bool isSigned = vecTypeHint.getIsSigned();
1936 llvmFunc->setMetadata(
1937 func.getVecTypeHintAttrName(),
1938 convertVecTypeHintToMDNode(llvmContext, llvmType, isSigned));
1939 }
1940
1941 if (std::optional<ArrayRef<int32_t>> workGroupSizeHint =
1942 func.getWorkGroupSizeHint()) {
1943 llvmFunc->setMetadata(
1944 func.getWorkGroupSizeHintAttrName(),
1945 convertIntegerArrayToMDNode(llvmContext, *workGroupSizeHint));
1946 }
1947
1948 if (std::optional<ArrayRef<int32_t>> reqdWorkGroupSize =
1949 func.getReqdWorkGroupSize()) {
1950 llvmFunc->setMetadata(
1951 func.getReqdWorkGroupSizeAttrName(),
1952 convertIntegerArrayToMDNode(llvmContext, *reqdWorkGroupSize));
1953 }
1954
1955 if (std::optional<uint32_t> intelReqdSubGroupSize =
1956 func.getIntelReqdSubGroupSize()) {
1957 llvmFunc->setMetadata(
1958 func.getIntelReqdSubGroupSizeAttrName(),
1959 convertIntegerToMDNode(llvmContext,
1960 llvm::APInt(32, *intelReqdSubGroupSize)));
1961 }
1962}
1963
1964static LogicalResult convertParameterAttr(llvm::AttrBuilder &attrBuilder,
1965 llvm::Attribute::AttrKind llvmKind,
1966 NamedAttribute namedAttr,
1967 ModuleTranslation &moduleTranslation,
1968 Location loc) {
1970 .Case([&](TypeAttr typeAttr) {
1971 attrBuilder.addTypeAttr(
1972 llvmKind, moduleTranslation.convertType(typeAttr.getValue()));
1973 return success();
1974 })
1975 .Case([&](IntegerAttr intAttr) {
1976 attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1977 return success();
1978 })
1979 .Case([&](UnitAttr) {
1980 attrBuilder.addAttribute(llvmKind);
1981 return success();
1982 })
1983 .Case([&](LLVM::ConstantRangeAttr rangeAttr) {
1984 attrBuilder.addConstantRangeAttr(
1985 llvmKind,
1986 llvm::ConstantRange(rangeAttr.getLower(), rangeAttr.getUpper()));
1987 return success();
1988 })
1989 .Default([loc](auto) {
1990 return emitError(loc, "unsupported parameter attribute type");
1991 });
1992}
1993
1994FailureOr<llvm::AttrBuilder>
1995ModuleTranslation::convertParameterAttrs(LLVMFuncOp func, int argIdx,
1996 DictionaryAttr paramAttrs) {
1997 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1998 auto attrNameToKindMapping = getAttrNameToKindMapping();
1999 Location loc = func.getLoc();
2000
2001 for (auto namedAttr : paramAttrs) {
2002 auto it = attrNameToKindMapping.find(namedAttr.getName());
2003 if (it != attrNameToKindMapping.end()) {
2004 llvm::Attribute::AttrKind llvmKind = it->second;
2005 if (failed(convertParameterAttr(attrBuilder, llvmKind, namedAttr, *this,
2006 loc)))
2007 return failure();
2008 } else if (namedAttr.getNameDialect()) {
2009 if (failed(iface.convertParameterAttr(func, argIdx, namedAttr, *this)))
2010 return failure();
2011 }
2012 }
2013
2014 return attrBuilder;
2015}
2016
2018 ArgAndResultAttrsOpInterface attrsOp, llvm::CallBase *call,
2019 ArrayRef<unsigned> immArgPositions) {
2020 // Convert the argument attributes.
2021 if (ArrayAttr argAttrsArray = attrsOp.getArgAttrsAttr()) {
2022 unsigned argAttrIdx = 0;
2023 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2024 immArgPositions.end());
2025 for (unsigned argIdx : llvm::seq<unsigned>(call->arg_size())) {
2026 if (argAttrIdx >= argAttrsArray.size())
2027 break;
2028 // Skip immediate arguments (they have no entries in argAttrsArray).
2029 if (immArgPositionsSet.contains(argIdx))
2030 continue;
2031 // Skip empty argument attributes.
2032 auto argAttrs = cast<DictionaryAttr>(argAttrsArray[argAttrIdx++]);
2033 if (argAttrs.empty())
2034 continue;
2035 // Convert and add attributes to the call instruction.
2036 FailureOr<llvm::AttrBuilder> attrBuilder =
2037 convertParameterAttrs(attrsOp->getLoc(), argAttrs);
2038 if (failed(attrBuilder))
2039 return failure();
2040 call->addParamAttrs(argIdx, *attrBuilder);
2041 }
2042 }
2043
2044 // Convert the result attributes.
2045 if (ArrayAttr resAttrsArray = attrsOp.getResAttrsAttr()) {
2046 if (!resAttrsArray.empty()) {
2047 auto resAttrs = cast<DictionaryAttr>(resAttrsArray[0]);
2048 FailureOr<llvm::AttrBuilder> attrBuilder =
2049 convertParameterAttrs(attrsOp->getLoc(), resAttrs);
2050 if (failed(attrBuilder))
2051 return failure();
2052 call->addRetAttrs(*attrBuilder);
2053 }
2054 }
2055
2056 return success();
2057}
2058
2059std::optional<llvm::Attribute>
2061 if (auto str = dyn_cast<StringAttr>(a))
2062 return llvm::Attribute::get(ctx, ("no-builtin-" + str.getValue()).str());
2063 return std::nullopt;
2064}
2065
2066std::optional<llvm::Attribute>
2068 mlir::NamedAttribute namedAttr) {
2069 StringAttr name = namedAttr.getName();
2070 Attribute value = namedAttr.getValue();
2071
2072 if (auto strVal = dyn_cast<StringAttr>(value))
2073 return llvm::Attribute::get(ctx, name.getValue(), strVal.getValue());
2074 if (mlir::isa<UnitAttr>(value))
2075 return llvm::Attribute::get(ctx, name.getValue());
2076 return std::nullopt;
2077}
2078
2079FailureOr<llvm::AttrBuilder>
2080ModuleTranslation::convertParameterAttrs(Location loc,
2081 DictionaryAttr paramAttrs) {
2082 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
2083 auto attrNameToKindMapping = getAttrNameToKindMapping();
2084
2085 for (auto namedAttr : paramAttrs) {
2086 auto it = attrNameToKindMapping.find(namedAttr.getName());
2087 if (it != attrNameToKindMapping.end()) {
2088 llvm::Attribute::AttrKind llvmKind = it->second;
2089 if (failed(convertParameterAttr(attrBuilder, llvmKind, namedAttr, *this,
2090 loc)))
2091 return failure();
2092 }
2093 }
2094
2095 return attrBuilder;
2096}
2097
2098LogicalResult ModuleTranslation::convertFunctionSignatures() {
2099 // Declare all functions first because there may be function calls that form a
2100 // call graph with cycles, global initializers that reference functions, or
2101 // metadata that references functions declared later in the module.
2102 for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
2103 llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
2104 function.getName(),
2105 cast<llvm::FunctionType>(convertType(function.getFunctionType())));
2106 llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
2107 mapFunction(function.getName(), llvmFunc);
2108 }
2109
2110 for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
2111 llvm::Function *llvmFunc = lookupFunction(function.getName());
2112 llvmFunc->setLinkage(convertLinkageToLLVM(function.getLinkage()));
2113 llvmFunc->setCallingConv(convertCConvToLLVM(function.getCConv()));
2114 addRuntimePreemptionSpecifier(function.getDsoLocal(), llvmFunc);
2115
2116 // Convert function attributes.
2117 convertFunctionAttributes(*this, function, llvmFunc);
2118
2119 // Convert function kernel attributes to metadata.
2120 convertFunctionKernelAttributes(function, llvmFunc, *this);
2121
2122 // Convert function_entry_count attribute to metadata.
2123 if (auto entryCount = function.getFunctionEntryCountAttr()) {
2124 ArrayRef<uint64_t> imports = entryCount.getImports();
2125 llvm::DenseSet<llvm::GlobalValue::GUID> importGUIDs;
2126 if (!imports.empty())
2127 importGUIDs.insert(imports.begin(), imports.end());
2128 llvm::MDBuilder metadataBuilder(llvmFunc->getContext());
2129 llvmFunc->setMetadata(
2130 llvm::LLVMContext::MD_prof,
2131 metadataBuilder.createFunctionEntryCount(
2132 entryCount.getEntryCount(),
2133 entryCount.getCountType() == ProfileCountType::Synthetic,
2134 imports.empty() ? nullptr : &importGUIDs));
2135 }
2136
2137 // Convert result attributes.
2138 if (ArrayAttr allResultAttrs = function.getAllResultAttrs()) {
2139 DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
2140 FailureOr<llvm::AttrBuilder> attrBuilder =
2141 convertParameterAttrs(function, -1, resultAttrs);
2142 if (failed(attrBuilder))
2143 return failure();
2144 llvmFunc->addRetAttrs(*attrBuilder);
2145 }
2146
2147 // Convert argument attributes.
2148 for (auto [argIdx, llvmArg] : llvm::enumerate(llvmFunc->args())) {
2149 if (DictionaryAttr argAttrs = function.getArgAttrDict(argIdx)) {
2150 FailureOr<llvm::AttrBuilder> attrBuilder =
2151 convertParameterAttrs(function, argIdx, argAttrs);
2152 if (failed(attrBuilder))
2153 return failure();
2154 llvmArg.addAttrs(*attrBuilder);
2155 }
2156 }
2157
2158 // Forward the pass-through attributes to LLVM.
2159 FailureOr<llvm::AttrBuilder> convertedPassthroughAttrs =
2160 convertMLIRAttributesToLLVM(function.getLoc(), llvmFunc->getContext(),
2161 function.getPassthroughAttr(),
2162 function.getPassthroughAttrName());
2163 if (failed(convertedPassthroughAttrs))
2164 return failure();
2165 llvmFunc->addFnAttrs(*convertedPassthroughAttrs);
2166
2167 // Convert visibility attribute.
2168 llvmFunc->setVisibility(convertVisibilityToLLVM(function.getVisibility_()));
2169
2170 // Convert the comdat attribute.
2171 if (std::optional<mlir::SymbolRefAttr> comdat = function.getComdat()) {
2172 auto selectorOp = cast<ComdatSelectorOp>(
2173 SymbolTable::lookupNearestSymbolFrom(function, *comdat));
2174 llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
2175 }
2176
2177 if (auto gc = function.getGarbageCollector())
2178 llvmFunc->setGC(gc->str());
2179
2180 if (auto unnamedAddr = function.getUnnamedAddr())
2181 llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
2182
2183 if (auto alignment = function.getAlignment())
2184 llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
2185
2186 // Translate the debug information for this function.
2187 debugTranslation->translate(function, *llvmFunc);
2188 }
2189
2190 return success();
2191}
2192
2193LogicalResult ModuleTranslation::convertFunctions() {
2194 // Convert functions.
2195 for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
2196 // Do not convert external functions, but do process dialect attributes
2197 // attached to them.
2198 if (function.isExternal()) {
2199 if (failed(convertDialectAttributes(function, {})))
2200 return failure();
2201 continue;
2202 }
2203
2204 if (failed(convertOneFunction(function)))
2205 return failure();
2206 }
2207
2208 return success();
2209}
2210
2211LogicalResult ModuleTranslation::convertIFuncs() {
2212 for (auto op : getModuleBody(mlirModule).getOps<IFuncOp>()) {
2213 llvm::Type *type = convertType(op.getIFuncType());
2214 llvm::GlobalValue::LinkageTypes linkage =
2215 convertLinkageToLLVM(op.getLinkage());
2216 llvm::Constant *resolver;
2217 if (auto *resolverFn = lookupFunction(op.getResolver())) {
2218 resolver = cast<llvm::Constant>(resolverFn);
2219 } else {
2220 Operation *aliasOp = symbolTable().lookupSymbolIn(parentLLVMModule(op),
2221 op.getResolverAttr());
2222 resolver = cast<llvm::Constant>(lookupAlias(aliasOp));
2223 }
2224
2225 auto *ifunc =
2226 llvm::GlobalIFunc::create(type, op.getAddressSpace(), linkage,
2227 op.getSymName(), resolver, llvmModule.get());
2228 addRuntimePreemptionSpecifier(op.getDsoLocal(), ifunc);
2229 ifunc->setUnnamedAddr(convertUnnamedAddrToLLVM(op.getUnnamedAddr()));
2230 ifunc->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
2231
2232 ifuncMapping.try_emplace(op, ifunc);
2233 }
2234
2235 return success();
2236}
2237
2238LogicalResult ModuleTranslation::convertComdats() {
2239 for (auto comdatOp : getModuleBody(mlirModule).getOps<ComdatOp>()) {
2240 for (auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
2241 llvm::Module *module = getLLVMModule();
2242 if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
2243 return emitError(selectorOp.getLoc())
2244 << "comdat selection symbols must be unique even in different "
2245 "comdat regions";
2246 llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
2247 comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
2248 comdatMapping.try_emplace(selectorOp, comdat);
2249 }
2250 }
2251 return success();
2252}
2253
2254LogicalResult ModuleTranslation::convertUnresolvedBlockAddress() {
2255 for (auto &[blockAddressOp, llvmCst] : unresolvedBlockAddressMapping) {
2256 BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
2257 llvm::BasicBlock *llvmBlock = lookupBlockAddress(blockAddressAttr);
2258 assert(llvmBlock && "expected LLVM blocks to be already translated");
2259
2260 // Update mapping with new block address constant.
2261 auto *llvmBlockAddr = llvm::BlockAddress::get(
2262 lookupFunction(blockAddressAttr.getFunction().getValue()), llvmBlock);
2263 llvmCst->replaceAllUsesWith(llvmBlockAddr);
2264 assert(llvmCst->use_empty() && "expected all uses to be replaced");
2265 cast<llvm::GlobalVariable>(llvmCst)->eraseFromParent();
2266 }
2267 unresolvedBlockAddressMapping.clear();
2268 return success();
2269}
2270
2271void ModuleTranslation::setAccessGroupsMetadata(AccessGroupOpInterface op,
2272 llvm::Instruction *inst) {
2273 if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
2274 inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
2275}
2276
2277llvm::MDNode *
2278ModuleTranslation::getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr) {
2279 auto [scopeIt, scopeInserted] =
2280 aliasScopeMetadataMapping.try_emplace(aliasScopeAttr, nullptr);
2281 if (!scopeInserted)
2282 return scopeIt->second;
2283 llvm::LLVMContext &ctx = llvmModule->getContext();
2284 auto dummy = llvm::MDNode::getTemporary(ctx, {});
2285 // Convert the domain metadata node if necessary.
2286 auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
2287 aliasScopeAttr.getDomain(), nullptr);
2288 if (insertedDomain) {
2290 // Placeholder for potential self-reference.
2291 operands.push_back(dummy.get());
2292 if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
2293 operands.push_back(llvm::MDString::get(ctx, description));
2294 domainIt->second = llvm::MDNode::get(ctx, operands);
2295 // Self-reference for uniqueness.
2296 llvm::Metadata *replacement;
2297 if (auto stringAttr =
2298 dyn_cast<StringAttr>(aliasScopeAttr.getDomain().getId()))
2299 replacement = llvm::MDString::get(ctx, stringAttr.getValue());
2300 else
2301 replacement = domainIt->second;
2302 domainIt->second->replaceOperandWith(0, replacement);
2303 }
2304 // Convert the scope metadata node.
2305 assert(domainIt->second && "Scope's domain should already be valid");
2307 // Placeholder for potential self-reference.
2308 operands.push_back(dummy.get());
2309 operands.push_back(domainIt->second);
2310 if (StringAttr description = aliasScopeAttr.getDescription())
2311 operands.push_back(llvm::MDString::get(ctx, description));
2312 scopeIt->second = llvm::MDNode::get(ctx, operands);
2313 // Self-reference for uniqueness.
2314 llvm::Metadata *replacement;
2315 if (auto stringAttr = dyn_cast<StringAttr>(aliasScopeAttr.getId()))
2316 replacement = llvm::MDString::get(ctx, stringAttr.getValue());
2317 else
2318 replacement = scopeIt->second;
2319 scopeIt->second->replaceOperandWith(0, replacement);
2320 return scopeIt->second;
2321}
2322
2324 ArrayRef<AliasScopeAttr> aliasScopeAttrs) {
2326 nodes.reserve(aliasScopeAttrs.size());
2327 for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
2328 nodes.push_back(getOrCreateAliasScope(aliasScopeAttr));
2329 return llvm::MDNode::get(getLLVMContext(), nodes);
2330}
2331
2332void ModuleTranslation::setAliasScopeMetadata(AliasAnalysisOpInterface op,
2333 llvm::Instruction *inst) {
2334 auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs, unsigned kind) {
2335 if (!aliasScopeAttrs || aliasScopeAttrs.empty())
2336 return;
2337 llvm::MDNode *node = getOrCreateAliasScopes(
2338 llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
2339 inst->setMetadata(kind, node);
2340 };
2341
2342 populateScopeMetadata(op.getAliasScopesOrNull(),
2343 llvm::LLVMContext::MD_alias_scope);
2344 populateScopeMetadata(op.getNoAliasScopesOrNull(),
2345 llvm::LLVMContext::MD_noalias);
2346}
2347
2348llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr) const {
2349 return tbaaMetadataMapping.lookup(tbaaAttr);
2350}
2351
2352void ModuleTranslation::setTBAAMetadata(AliasAnalysisOpInterface op,
2353 llvm::Instruction *inst) {
2354 ArrayAttr tagRefs = op.getTBAATagsOrNull();
2355 if (!tagRefs || tagRefs.empty())
2356 return;
2357
2358 // LLVM IR currently does not support attaching more than one TBAA access tag
2359 // to a memory accessing instruction. It may be useful to support this in
2360 // future, but for the time being just ignore the metadata if MLIR operation
2361 // has multiple access tags.
2362 if (tagRefs.size() > 1) {
2363 op.emitWarning() << "TBAA access tags were not translated, because LLVM "
2364 "IR only supports a single tag per instruction";
2365 return;
2366 }
2367
2368 llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
2369 inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
2370}
2371
2373 DereferenceableOpInterface op, llvm::Instruction *inst) {
2374 DereferenceableAttr derefAttr = op.getDereferenceableOrNull();
2375 if (!derefAttr)
2376 return;
2377
2378 llvm::MDNode *derefSizeNode = llvm::MDNode::get(
2380 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2381 llvm::IntegerType::get(getLLVMContext(), 64), derefAttr.getBytes())));
2382 unsigned kindId = derefAttr.getMayBeNull()
2383 ? llvm::LLVMContext::MD_dereferenceable_or_null
2384 : llvm::LLVMContext::MD_dereferenceable;
2385 inst->setMetadata(kindId, derefSizeNode);
2386}
2387
2388void ModuleTranslation::setBranchWeightsMetadata(WeightedBranchOpInterface op) {
2389 SmallVector<uint32_t> weights;
2390 llvm::transform(op.getWeights(), std::back_inserter(weights),
2391 [](int32_t value) { return static_cast<uint32_t>(value); });
2392 if (weights.empty())
2393 return;
2394
2395 llvm::Instruction *inst = isa<CallOp>(op) ? lookupCall(op) : lookupBranch(op);
2396 assert(inst && "expected the operation to have a mapping to an instruction");
2397 inst->setMetadata(
2398 llvm::LLVMContext::MD_prof,
2399 llvm::MDBuilder(getLLVMContext()).createBranchWeights(weights));
2400}
2401
2402LogicalResult ModuleTranslation::createTBAAMetadata() {
2403 llvm::LLVMContext &ctx = llvmModule->getContext();
2404 llvm::IntegerType *offsetTy = llvm::IntegerType::get(ctx, 64);
2405
2406 // Walk the entire module and create all metadata nodes for the TBAA
2407 // attributes. The code below relies on two invariants of the
2408 // `AttrTypeWalker`:
2409 // 1. Attributes are visited in post-order: Since the attributes create a DAG,
2410 // this ensures that any lookups into `tbaaMetadataMapping` for child
2411 // attributes succeed.
2412 // 2. Attributes are only ever visited once: This way we don't leak any
2413 // LLVM metadata instances.
2414 AttrTypeWalker walker;
2415 walker.addWalk([&](TBAARootAttr root) {
2416 llvm::MDNode *node;
2417 if (StringAttr id = root.getId()) {
2418 node = llvm::MDNode::get(ctx, llvm::MDString::get(ctx, id));
2419 } else {
2420 // Anonymous root nodes are self-referencing.
2421 auto selfRef = llvm::MDNode::getTemporary(ctx, {});
2422 node = llvm::MDNode::get(ctx, {selfRef.get()});
2423 node->replaceOperandWith(0, node);
2424 }
2425 tbaaMetadataMapping.insert({root, node});
2426 });
2427
2428 walker.addWalk([&](TBAATypeDescriptorAttr descriptor) {
2429 SmallVector<llvm::Metadata *> operands;
2430 operands.push_back(llvm::MDString::get(ctx, descriptor.getId()));
2431 for (TBAAMemberAttr member : descriptor.getMembers()) {
2432 operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
2433 operands.push_back(llvm::ConstantAsMetadata::get(
2434 llvm::ConstantInt::get(offsetTy, member.getOffset())));
2435 }
2436
2437 tbaaMetadataMapping.insert({descriptor, llvm::MDNode::get(ctx, operands)});
2438 });
2439
2440 walker.addWalk([&](TBAATagAttr tag) {
2441 SmallVector<llvm::Metadata *> operands;
2442
2443 operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
2444 operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
2445
2446 operands.push_back(llvm::ConstantAsMetadata::get(
2447 llvm::ConstantInt::get(offsetTy, tag.getOffset())));
2448 if (tag.getConstant())
2449 operands.push_back(
2450 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(offsetTy, 1)));
2451
2452 tbaaMetadataMapping.insert({tag, llvm::MDNode::get(ctx, operands)});
2453 });
2454
2455 mlirModule->walk([&](AliasAnalysisOpInterface analysisOpInterface) {
2456 if (auto attr = analysisOpInterface.getTBAATagsOrNull())
2457 walker.walk(attr);
2458 });
2459
2460 return success();
2461}
2462
2463LogicalResult ModuleTranslation::createIdentMetadata() {
2464 if (auto attr = mlirModule->getAttrOfType<StringAttr>(
2465 LLVMDialect::getIdentAttrName())) {
2466 StringRef ident = attr;
2467 llvm::LLVMContext &ctx = llvmModule->getContext();
2468 llvm::NamedMDNode *namedMd =
2469 llvmModule->getOrInsertNamedMetadata(LLVMDialect::getIdentAttrName());
2470 llvm::MDNode *md = llvm::MDNode::get(ctx, llvm::MDString::get(ctx, ident));
2471 namedMd->addOperand(md);
2472 }
2473
2474 return success();
2475}
2476
2477LogicalResult ModuleTranslation::createCommandlineMetadata() {
2478 if (auto attr = mlirModule->getAttrOfType<StringAttr>(
2479 LLVMDialect::getCommandlineAttrName())) {
2480 StringRef cmdLine = attr;
2481 llvm::LLVMContext &ctx = llvmModule->getContext();
2482 llvm::NamedMDNode *nmd = llvmModule->getOrInsertNamedMetadata(
2483 LLVMDialect::getCommandlineAttrName());
2484 llvm::MDNode *md =
2485 llvm::MDNode::get(ctx, llvm::MDString::get(ctx, cmdLine));
2486 nmd->addOperand(md);
2487 }
2488
2489 return success();
2490}
2491
2492LogicalResult ModuleTranslation::createDependentLibrariesMetadata() {
2493 if (auto dependentLibrariesAttr = mlirModule->getDiscardableAttr(
2494 LLVM::LLVMDialect::getDependentLibrariesAttrName())) {
2495 auto *nmd =
2496 llvmModule->getOrInsertNamedMetadata("llvm.dependent-libraries");
2497 llvm::LLVMContext &ctx = llvmModule->getContext();
2498 for (auto libAttr :
2499 cast<ArrayAttr>(dependentLibrariesAttr).getAsRange<StringAttr>()) {
2500 auto *md =
2501 llvm::MDNode::get(ctx, llvm::MDString::get(ctx, libAttr.getValue()));
2502 nmd->addOperand(md);
2503 }
2504 }
2505 return success();
2506}
2507
2509 llvm::Instruction *inst) {
2510 LoopAnnotationAttr attr =
2512 .Case<LLVM::BrOp, LLVM::CondBrOp>(
2513 [](auto branchOp) { return branchOp.getLoopAnnotationAttr(); });
2514 if (!attr)
2515 return;
2516 llvm::MDNode *loopMD =
2517 loopAnnotationTranslation->translateLoopAnnotation(attr, op);
2518 inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
2519}
2520
2521void ModuleTranslation::setDisjointFlag(Operation *op, llvm::Value *value) {
2522 auto iface = cast<DisjointFlagInterface>(op);
2523 // We do a dyn_cast here in case the value got folded into a constant.
2524 if (auto *disjointInst = dyn_cast<llvm::PossiblyDisjointInst>(value))
2525 disjointInst->setIsDisjoint(iface.getIsDisjoint());
2526}
2527
2529 return typeTranslator.translateType(type);
2530}
2531
2532/// A helper to look up remapped operands in the value remapping table.
2535 remapped.reserve(values.size());
2536 for (Value v : values)
2537 remapped.push_back(lookupValue(v));
2538 return remapped;
2539}
2540
2541llvm::OpenMPIRBuilder *ModuleTranslation::getOpenMPBuilder() {
2542 if (!ompBuilder) {
2543 ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
2544
2545 // Flags represented as top-level OpenMP dialect attributes are set in
2546 // `OpenMPDialectLLVMIRTranslationInterface::amendOperation()`. Here we set
2547 // the default configuration.
2548 llvm::OpenMPIRBuilderConfig config(
2549 /* IsTargetDevice = */ false, /* IsGPU = */ false,
2550 /* OpenMPOffloadMandatory = */ false,
2551 /* HasRequiresReverseOffload = */ false,
2552 /* HasRequiresUnifiedAddress = */ false,
2553 /* HasRequiresUnifiedSharedMemory = */ false,
2554 /* HasRequiresDynamicAllocators = */ false);
2555 unsigned int defaultAS =
2556 llvmModule->getDataLayout().getProgramAddressSpace();
2557 config.setDefaultTargetAS(defaultAS);
2558 config.setRuntimeCC(llvmModule->getTargetTriple().isSPIRV()
2559 ? llvm::CallingConv::SPIR_FUNC
2560 : llvm::CallingConv::C);
2561 ompBuilder->setConfig(std::move(config));
2562 ompBuilder->initialize();
2563 }
2564 return ompBuilder.get();
2565}
2566
2567llvm::vfs::FileSystem &ModuleTranslation::getFileSystem() {
2568 if (fileSystem)
2569 return *fileSystem;
2570 return *llvm::vfs::getRealFileSystem();
2571}
2572
2574 llvm::DILocalScope *scope) {
2575 return debugTranslation->translateLoc(loc, scope);
2576}
2577
2578llvm::DIExpression *
2579ModuleTranslation::translateExpression(LLVM::DIExpressionAttr attr) {
2580 return debugTranslation->translateExpression(attr);
2581}
2582
2583llvm::DIGlobalVariableExpression *
2585 LLVM::DIGlobalVariableExpressionAttr attr) {
2586 return debugTranslation->translateGlobalVariableExpression(attr);
2587}
2588
2590 return debugTranslation->translate(attr);
2591}
2592
2593llvm::RoundingMode
2594ModuleTranslation::translateRoundingMode(LLVM::RoundingMode rounding) {
2595 return convertRoundingModeToLLVM(rounding);
2596}
2597
2599 LLVM::FPExceptionBehavior exceptionBehavior) {
2600 return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
2601}
2602
2603llvm::NamedMDNode *
2605 return llvmModule->getOrInsertNamedMetadata(name);
2606}
2607
2608static std::unique_ptr<llvm::Module>
2609prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
2610 StringRef name) {
2611 m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
2612 auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
2613 if (auto dataLayoutAttr =
2614 m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
2615 llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
2616 } else {
2617 FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(""));
2618 if (auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
2619 if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
2620 llvmDataLayout =
2621 translateDataLayout(spec, DataLayout(iface), m->getLoc());
2622 }
2623 } else if (auto mod = dyn_cast<ModuleOp>(m)) {
2624 if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
2625 llvmDataLayout =
2626 translateDataLayout(spec, DataLayout(mod), m->getLoc());
2627 }
2628 }
2629 if (failed(llvmDataLayout))
2630 return nullptr;
2631 llvmModule->setDataLayout(*llvmDataLayout);
2632 }
2633 if (auto targetTripleAttr =
2634 m->getDiscardableAttr(LLVM::LLVMDialect::getTargetTripleAttrName()))
2635 llvmModule->setTargetTriple(
2636 llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
2637
2638 if (auto asmAttr = m->getDiscardableAttr(
2639 LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
2640 auto asmArrayAttr = dyn_cast<ArrayAttr>(asmAttr);
2641 if (!asmArrayAttr) {
2642 m->emitError("expected an array attribute for a module level asm");
2643 return nullptr;
2644 }
2645
2646 for (Attribute elt : asmArrayAttr) {
2647 auto asmStrAttr = dyn_cast<StringAttr>(elt);
2648 if (!asmStrAttr) {
2649 m->emitError(
2650 "expected a string attribute for each entry of a module level asm");
2651 return nullptr;
2652 }
2653 llvmModule->appendModuleInlineAsm(asmStrAttr.getValue());
2654 }
2655 }
2656
2657 return llvmModule;
2658}
2659
2660std::unique_ptr<llvm::Module>
2661mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
2662 StringRef name, bool disableVerification,
2663 llvm::vfs::FileSystem *fs) {
2664 if (!satisfiesLLVMModule(module)) {
2665 module->emitOpError("can not be translated to an LLVMIR module");
2666 return nullptr;
2667 }
2668
2669 std::unique_ptr<llvm::Module> llvmModule =
2670 prepareLLVMModule(module, llvmContext, name);
2671 if (!llvmModule)
2672 return nullptr;
2673
2676
2677 ModuleTranslation translator(module, std::move(llvmModule), fs);
2678 llvm::IRBuilder<llvm::TargetFolder> llvmBuilder(
2679 llvmContext,
2680 llvm::TargetFolder(translator.getLLVMModule()->getDataLayout()));
2681
2682 // Convert module before functions and operations inside, so dialect
2683 // attributes can be used to change dialect-specific global configurations via
2684 // `amendOperation()`. These configurations can then influence the translation
2685 // of operations afterwards.
2686 if (failed(translator.convertOperation(*module, llvmBuilder)))
2687 return nullptr;
2688
2689 if (failed(translator.convertComdats()))
2690 return nullptr;
2691 if (failed(translator.convertFunctionSignatures()))
2692 return nullptr;
2693 if (failed(translator.convertGlobalsAndAliases()))
2694 return nullptr;
2695 if (failed(translator.convertIFuncs()))
2696 return nullptr;
2697 if (failed(translator.convertFunctionMetadata()))
2698 return nullptr;
2699 if (failed(translator.createTBAAMetadata()))
2700 return nullptr;
2701 if (failed(translator.createIdentMetadata()))
2702 return nullptr;
2703 if (failed(translator.createCommandlineMetadata()))
2704 return nullptr;
2705 if (failed(translator.createDependentLibrariesMetadata()))
2706 return nullptr;
2707
2708 // Convert other top-level operations if possible.
2709 for (Operation &o : getModuleBody(module).getOperations()) {
2710 if (!isa<LLVM::LLVMFuncOp, LLVM::AliasOp, LLVM::GlobalOp,
2711 LLVM::GlobalCtorsOp, LLVM::GlobalDtorsOp, LLVM::ComdatOp,
2712 LLVM::IFuncOp>(&o) &&
2713 !o.hasTrait<OpTrait::IsTerminator>() &&
2714 failed(translator.convertOperation(o, llvmBuilder))) {
2715 return nullptr;
2716 }
2717 }
2718
2719 // Operations in function bodies with symbolic references must be converted
2720 // after the top-level operations they refer to are declared, so we do it
2721 // last.
2722 if (failed(translator.convertFunctions()))
2723 return nullptr;
2724
2725 // Now that all MLIR blocks are resolved into LLVM ones, patch block address
2726 // constants to point to the correct blocks.
2727 if (failed(translator.convertUnresolvedBlockAddress()))
2728 return nullptr;
2729
2730 // Add the necessary debug info module flags, if they were not encoded in MLIR
2731 // beforehand.
2732 translator.debugTranslation->addModuleFlagsIfNotPresent();
2733
2734 // Call the OpenMP IR Builder callbacks prior to verifying the module
2735 if (auto *ompBuilder = translator.getOpenMPBuilder())
2736 ompBuilder->finalize();
2737
2738 if (!disableVerification &&
2739 llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
2740 return nullptr;
2741
2742 return std::move(translator.llvmModule);
2743}
return success()
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:33
iterator_range< pred_iterator > getPredecessors()
Definition Block.h:264
Operation & front()
Definition Block.h:177
Operation * getTerminator()
Get the terminator operation of this block.
Definition Block.cpp:249
BlockArgListType getArguments()
Definition Block.h:111
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
Definition Block.h:236
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.
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::OpenMPIRBuilder * getOpenMPBuilder()
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
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.
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:164
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
Definition Attributes.h:179
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:478
Value getOperand(unsigned idx)
Definition Operation.h:375
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Definition Operation.h:579
unsigned getNumSuccessors()
Definition Operation.h:751
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:432
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:682
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition Operation.h:403
Block * getSuccessor(unsigned index)
Definition Operation.h:753
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,...
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
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:717
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:307
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:139
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:120
llvm::function_ref< Fn > function_ref
Definition LLVM.h:147