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