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