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