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