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