MLIR  14.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 "DebugTranslation.h"
20 #include "mlir/IR/Attributes.h"
21 #include "mlir/IR/BuiltinOps.h"
22 #include "mlir/IR/BuiltinTypes.h"
24 #include "mlir/Support/LLVM.h"
27 #include "llvm/ADT/TypeSwitch.h"
28 
29 #include "llvm/ADT/PostOrderIterator.h"
30 #include "llvm/ADT/SetVector.h"
31 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
32 #include "llvm/IR/BasicBlock.h"
33 #include "llvm/IR/CFG.h"
34 #include "llvm/IR/Constants.h"
35 #include "llvm/IR/DerivedTypes.h"
36 #include "llvm/IR/IRBuilder.h"
37 #include "llvm/IR/InlineAsm.h"
38 #include "llvm/IR/IntrinsicsNVPTX.h"
39 #include "llvm/IR/LLVMContext.h"
40 #include "llvm/IR/MDBuilder.h"
41 #include "llvm/IR/Module.h"
42 #include "llvm/IR/Verifier.h"
43 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
44 #include "llvm/Transforms/Utils/Cloning.h"
45 #include "llvm/Transforms/Utils/ModuleUtils.h"
46 
47 using namespace mlir;
48 using namespace mlir::LLVM;
49 using namespace mlir::LLVM::detail;
50 
51 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
52 
53 /// Builds a constant of a sequential LLVM type `type`, potentially containing
54 /// other sequential types recursively, from the individual constant values
55 /// provided in `constants`. `shape` contains the number of elements in nested
56 /// sequential types. Reports errors at `loc` and returns nullptr on error.
57 static llvm::Constant *
59  ArrayRef<int64_t> shape, llvm::Type *type,
60  Location loc) {
61  if (shape.empty()) {
62  llvm::Constant *result = constants.front();
63  constants = constants.drop_front();
64  return result;
65  }
66 
67  llvm::Type *elementType;
68  if (auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
69  elementType = arrayTy->getElementType();
70  } else if (auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
71  elementType = vectorTy->getElementType();
72  } else {
73  emitError(loc) << "expected sequential LLVM types wrapping a scalar";
74  return nullptr;
75  }
76 
78  nested.reserve(shape.front());
79  for (int64_t i = 0; i < shape.front(); ++i) {
80  nested.push_back(buildSequentialConstant(constants, shape.drop_front(),
81  elementType, loc));
82  if (!nested.back())
83  return nullptr;
84  }
85 
86  if (shape.size() == 1 && type->isVectorTy())
87  return llvm::ConstantVector::get(nested);
88  return llvm::ConstantArray::get(
89  llvm::ArrayType::get(elementType, shape.front()), nested);
90 }
91 
92 /// Returns the first non-sequential type nested in sequential types.
93 static llvm::Type *getInnermostElementType(llvm::Type *type) {
94  do {
95  if (auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
96  type = arrayTy->getElementType();
97  } else if (auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
98  type = vectorTy->getElementType();
99  } else {
100  return type;
101  }
102  } while (true);
103 }
104 
105 /// Convert a dense elements attribute to an LLVM IR constant using its raw data
106 /// storage if possible. This supports elements attributes of tensor or vector
107 /// type and avoids constructing separate objects for individual values of the
108 /// innermost dimension. Constants for other dimensions are still constructed
109 /// recursively. Returns null if constructing from raw data is not supported for
110 /// this type, e.g., element type is not a power-of-two-sized primitive. Reports
111 /// other errors at `loc`.
112 static llvm::Constant *
114  llvm::Type *llvmType,
115  const ModuleTranslation &moduleTranslation) {
116  if (!denseElementsAttr)
117  return nullptr;
118 
119  llvm::Type *innermostLLVMType = getInnermostElementType(llvmType);
120  if (!llvm::ConstantDataSequential::isElementTypeCompatible(innermostLLVMType))
121  return nullptr;
122 
123  ShapedType type = denseElementsAttr.getType();
124  if (type.getNumElements() == 0)
125  return nullptr;
126 
127  // Compute the shape of all dimensions but the innermost. Note that the
128  // innermost dimension may be that of the vector element type.
129  bool hasVectorElementType = type.getElementType().isa<VectorType>();
130  unsigned numAggregates =
131  denseElementsAttr.getNumElements() /
132  (hasVectorElementType ? 1
133  : denseElementsAttr.getType().getShape().back());
134  ArrayRef<int64_t> outerShape = type.getShape();
135  if (!hasVectorElementType)
136  outerShape = outerShape.drop_back();
137 
138  // Handle the case of vector splat, LLVM has special support for it.
139  if (denseElementsAttr.isSplat() &&
140  (type.isa<VectorType>() || hasVectorElementType)) {
142  innermostLLVMType, denseElementsAttr.getSplatValue<Attribute>(), loc,
143  moduleTranslation, /*isTopLevel=*/false);
144  llvm::Constant *splatVector =
145  llvm::ConstantDataVector::getSplat(0, splatValue);
146  SmallVector<llvm::Constant *> constants(numAggregates, splatVector);
147  ArrayRef<llvm::Constant *> constantsRef = constants;
148  return buildSequentialConstant(constantsRef, outerShape, llvmType, loc);
149  }
150  if (denseElementsAttr.isSplat())
151  return nullptr;
152 
153  // In case of non-splat, create a constructor for the innermost constant from
154  // a piece of raw data.
155  std::function<llvm::Constant *(StringRef)> buildCstData;
156  if (type.isa<TensorType>()) {
157  auto vectorElementType = type.getElementType().dyn_cast<VectorType>();
158  if (vectorElementType && vectorElementType.getRank() == 1) {
159  buildCstData = [&](StringRef data) {
160  return llvm::ConstantDataVector::getRaw(
161  data, vectorElementType.getShape().back(), innermostLLVMType);
162  };
163  } else if (!vectorElementType) {
164  buildCstData = [&](StringRef data) {
165  return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
166  innermostLLVMType);
167  };
168  }
169  } else if (type.isa<VectorType>()) {
170  buildCstData = [&](StringRef data) {
171  return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
172  innermostLLVMType);
173  };
174  }
175  if (!buildCstData)
176  return nullptr;
177 
178  // Create innermost constants and defer to the default constant creation
179  // mechanism for other dimensions.
181  unsigned aggregateSize = denseElementsAttr.getType().getShape().back() *
182  (innermostLLVMType->getScalarSizeInBits() / 8);
183  constants.reserve(numAggregates);
184  for (unsigned i = 0; i < numAggregates; ++i) {
185  StringRef data(denseElementsAttr.getRawData().data() + i * aggregateSize,
186  aggregateSize);
187  constants.push_back(buildCstData(data));
188  }
189 
190  ArrayRef<llvm::Constant *> constantsRef = constants;
191  return buildSequentialConstant(constantsRef, outerShape, llvmType, loc);
192 }
193 
194 /// Create an LLVM IR constant of `llvmType` from the MLIR attribute `attr`.
195 /// This currently supports integer, floating point, splat and dense element
196 /// attributes and combinations thereof. Also, an array attribute with two
197 /// elements is supported to represent a complex constant. In case of error,
198 /// report it to `loc` and return nullptr.
200  llvm::Type *llvmType, Attribute attr, Location loc,
201  const ModuleTranslation &moduleTranslation, bool isTopLevel) {
202  if (!attr)
203  return llvm::UndefValue::get(llvmType);
204  if (auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
205  if (!isTopLevel) {
206  emitError(loc, "nested struct types are not supported in constants");
207  return nullptr;
208  }
209  auto arrayAttr = attr.cast<ArrayAttr>();
210  llvm::Type *elementType = structType->getElementType(0);
211  llvm::Constant *real = getLLVMConstant(elementType, arrayAttr[0], loc,
212  moduleTranslation, false);
213  if (!real)
214  return nullptr;
215  llvm::Constant *imag = getLLVMConstant(elementType, arrayAttr[1], loc,
216  moduleTranslation, false);
217  if (!imag)
218  return nullptr;
219  return llvm::ConstantStruct::get(structType, {real, imag});
220  }
221  // For integer types, we allow a mismatch in sizes as the index type in
222  // MLIR might have a different size than the index type in the LLVM module.
223  if (auto intAttr = attr.dyn_cast<IntegerAttr>())
224  return llvm::ConstantInt::get(
225  llvmType,
226  intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth()));
227  if (auto floatAttr = attr.dyn_cast<FloatAttr>()) {
228  if (llvmType !=
229  llvm::Type::getFloatingPointTy(llvmType->getContext(),
230  floatAttr.getValue().getSemantics())) {
231  emitError(loc, "FloatAttr does not match expected type of the constant");
232  return nullptr;
233  }
234  return llvm::ConstantFP::get(llvmType, floatAttr.getValue());
235  }
236  if (auto funcAttr = attr.dyn_cast<FlatSymbolRefAttr>())
237  return llvm::ConstantExpr::getBitCast(
238  moduleTranslation.lookupFunction(funcAttr.getValue()), llvmType);
239  if (auto splatAttr = attr.dyn_cast<SplatElementsAttr>()) {
240  llvm::Type *elementType;
241  uint64_t numElements;
242  if (auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
243  elementType = arrayTy->getElementType();
244  numElements = arrayTy->getNumElements();
245  } else {
246  auto *vectorTy = cast<llvm::FixedVectorType>(llvmType);
247  elementType = vectorTy->getElementType();
248  numElements = vectorTy->getNumElements();
249  }
250  // Splat value is a scalar. Extract it only if the element type is not
251  // another sequence type. The recursion terminates because each step removes
252  // one outer sequential type.
253  bool elementTypeSequential =
254  isa<llvm::ArrayType, llvm::VectorType>(elementType);
256  elementType,
257  elementTypeSequential ? splatAttr
258  : splatAttr.getSplatValue<Attribute>(),
259  loc, moduleTranslation, false);
260  if (!child)
261  return nullptr;
262  if (llvmType->isVectorTy())
263  return llvm::ConstantVector::getSplat(
264  llvm::ElementCount::get(numElements, /*Scalable=*/false), child);
265  if (llvmType->isArrayTy()) {
266  auto *arrayType = llvm::ArrayType::get(elementType, numElements);
267  SmallVector<llvm::Constant *, 8> constants(numElements, child);
268  return llvm::ConstantArray::get(arrayType, constants);
269  }
270  }
271 
272  // Try using raw elements data if possible.
273  if (llvm::Constant *result =
275  llvmType, moduleTranslation)) {
276  return result;
277  }
278 
279  // Fall back to element-by-element construction otherwise.
280  if (auto elementsAttr = attr.dyn_cast<ElementsAttr>()) {
281  assert(elementsAttr.getType().hasStaticShape());
282  assert(!elementsAttr.getType().getShape().empty() &&
283  "unexpected empty elements attribute shape");
284 
286  constants.reserve(elementsAttr.getNumElements());
287  llvm::Type *innermostType = getInnermostElementType(llvmType);
288  for (auto n : elementsAttr.getValues<Attribute>()) {
289  constants.push_back(
290  getLLVMConstant(innermostType, n, loc, moduleTranslation, false));
291  if (!constants.back())
292  return nullptr;
293  }
294  ArrayRef<llvm::Constant *> constantsRef = constants;
296  constantsRef, elementsAttr.getType().getShape(), llvmType, loc);
297  assert(constantsRef.empty() && "did not consume all elemental constants");
298  return result;
299  }
300 
301  if (auto stringAttr = attr.dyn_cast<StringAttr>()) {
302  return llvm::ConstantDataArray::get(
303  moduleTranslation.getLLVMContext(),
304  ArrayRef<char>{stringAttr.getValue().data(),
305  stringAttr.getValue().size()});
306  }
307  emitError(loc, "unsupported constant value");
308  return nullptr;
309 }
310 
311 ModuleTranslation::ModuleTranslation(Operation *module,
312  std::unique_ptr<llvm::Module> llvmModule)
313  : mlirModule(module), llvmModule(std::move(llvmModule)),
314  debugTranslation(
315  std::make_unique<DebugTranslation>(module, *this->llvmModule)),
316  typeTranslator(this->llvmModule->getContext()),
317  iface(module->getContext()) {
318  assert(satisfiesLLVMModule(mlirModule) &&
319  "mlirModule should honor LLVM's module semantics.");
320 }
321 ModuleTranslation::~ModuleTranslation() {
322  if (ompBuilder)
323  ompBuilder->finalize();
324 }
325 
327  SmallVector<Region *> toProcess;
328  toProcess.push_back(&region);
329  while (!toProcess.empty()) {
330  Region *current = toProcess.pop_back_val();
331  for (Block &block : *current) {
332  blockMapping.erase(&block);
333  for (Value arg : block.getArguments())
334  valueMapping.erase(arg);
335  for (Operation &op : block) {
336  for (Value value : op.getResults())
337  valueMapping.erase(value);
338  if (op.hasSuccessors())
339  branchMapping.erase(&op);
340  if (isa<LLVM::GlobalOp>(op))
341  globalsMapping.erase(&op);
342  accessGroupMetadataMapping.erase(&op);
343  llvm::append_range(
344  toProcess,
345  llvm::map_range(op.getRegions(), [](Region &r) { return &r; }));
346  }
347  }
348  }
349 }
350 
351 /// Get the SSA value passed to the current block from the terminator operation
352 /// of its predecessor.
353 static Value getPHISourceValue(Block *current, Block *pred,
354  unsigned numArguments, unsigned index) {
355  Operation &terminator = *pred->getTerminator();
356  if (isa<LLVM::BrOp>(terminator))
357  return terminator.getOperand(index);
358 
359  SuccessorRange successors = terminator.getSuccessors();
360  assert(std::adjacent_find(successors.begin(), successors.end()) ==
361  successors.end() &&
362  "successors with arguments in LLVM branches must be different blocks");
363  (void)successors;
364 
365  // For instructions that branch based on a condition value, we need to take
366  // the operands for the branch that was taken.
367  if (auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
368  // For conditional branches, we take the operands from either the "true" or
369  // the "false" branch.
370  return condBranchOp.getSuccessor(0) == current
371  ? condBranchOp.getTrueDestOperands()[index]
372  : condBranchOp.getFalseDestOperands()[index];
373  }
374 
375  if (auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
376  // For switches, we take the operands from either the default case, or from
377  // the case branch that was taken.
378  if (switchOp.getDefaultDestination() == current)
379  return switchOp.getDefaultOperands()[index];
380  for (auto i : llvm::enumerate(switchOp.getCaseDestinations()))
381  if (i.value() == current)
382  return switchOp.getCaseOperands(i.index())[index];
383  }
384 
385  llvm_unreachable("only branch or switch operations can be terminators of a "
386  "block that has successors");
387 }
388 
389 /// Connect the PHI nodes to the results of preceding blocks.
391  const ModuleTranslation &state) {
392  // Skip the first block, it cannot be branched to and its arguments correspond
393  // to the arguments of the LLVM function.
394  for (auto it = std::next(region.begin()), eit = region.end(); it != eit;
395  ++it) {
396  Block *bb = &*it;
397  llvm::BasicBlock *llvmBB = state.lookupBlock(bb);
398  auto phis = llvmBB->phis();
399  auto numArguments = bb->getNumArguments();
400  assert(numArguments == std::distance(phis.begin(), phis.end()));
401  for (auto &numberedPhiNode : llvm::enumerate(phis)) {
402  auto &phiNode = numberedPhiNode.value();
403  unsigned index = numberedPhiNode.index();
404  for (auto *pred : bb->getPredecessors()) {
405  // Find the LLVM IR block that contains the converted terminator
406  // instruction and use it in the PHI node. Note that this block is not
407  // necessarily the same as state.lookupBlock(pred), some operations
408  // (in particular, OpenMP operations using OpenMPIRBuilder) may have
409  // split the blocks.
410  llvm::Instruction *terminator =
411  state.lookupBranch(pred->getTerminator());
412  assert(terminator && "missing the mapping for a terminator");
413  phiNode.addIncoming(
414  state.lookupValue(getPHISourceValue(bb, pred, numArguments, index)),
415  terminator->getParent());
416  }
417  }
418  }
419 }
420 
421 /// Sort function blocks topologically.
424  // For each block that has not been visited yet (i.e. that has no
425  // predecessors), add it to the list as well as its successors.
426  SetVector<Block *> blocks;
427  for (Block &b : region) {
428  if (blocks.count(&b) == 0) {
429  llvm::ReversePostOrderTraversal<Block *> traversal(&b);
430  blocks.insert(traversal.begin(), traversal.end());
431  }
432  }
433  assert(blocks.size() == region.getBlocks().size() &&
434  "some blocks are not sorted");
435 
436  return blocks;
437 }
438 
440  llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic,
442  llvm::Module *module = builder.GetInsertBlock()->getModule();
443  llvm::Function *fn = llvm::Intrinsic::getDeclaration(module, intrinsic, tys);
444  return builder.CreateCall(fn, args);
445 }
446 
447 /// Given a single MLIR operation, create the corresponding LLVM IR operation
448 /// using the `builder`.
450 ModuleTranslation::convertOperation(Operation &op,
451  llvm::IRBuilderBase &builder) {
452  const LLVMTranslationDialectInterface *opIface = iface.getInterfaceFor(&op);
453  if (!opIface)
454  return op.emitError("cannot be converted to LLVM IR: missing "
455  "`LLVMTranslationDialectInterface` registration for "
456  "dialect for op: ")
457  << op.getName();
458 
459  if (failed(opIface->convertOperation(&op, builder, *this)))
460  return op.emitError("LLVM Translation failed for operation: ")
461  << op.getName();
462 
463  return convertDialectAttributes(&op);
464 }
465 
466 /// Convert block to LLVM IR. Unless `ignoreArguments` is set, emit PHI nodes
467 /// to define values corresponding to the MLIR block arguments. These nodes
468 /// are not connected to the source basic blocks, which may not exist yet. Uses
469 /// `builder` to construct the LLVM IR. Expects the LLVM IR basic block to have
470 /// been created for `bb` and included in the block mapping. Inserts new
471 /// instructions at the end of the block and leaves `builder` in a state
472 /// suitable for further insertion into the end of the block.
474  llvm::IRBuilderBase &builder) {
475  builder.SetInsertPoint(lookupBlock(&bb));
476  auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
477 
478  // Before traversing operations, make block arguments available through
479  // value remapping and PHI nodes, but do not add incoming edges for the PHI
480  // nodes just yet: those values may be defined by this or following blocks.
481  // This step is omitted if "ignoreArguments" is set. The arguments of the
482  // first block have been already made available through the remapping of
483  // LLVM function arguments.
484  if (!ignoreArguments) {
485  auto predecessors = bb.getPredecessors();
486  unsigned numPredecessors =
487  std::distance(predecessors.begin(), predecessors.end());
488  for (auto arg : bb.getArguments()) {
489  auto wrappedType = arg.getType();
490  if (!isCompatibleType(wrappedType))
491  return emitError(bb.front().getLoc(),
492  "block argument does not have an LLVM type");
493  llvm::Type *type = convertType(wrappedType);
494  llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
495  mapValue(arg, phi);
496  }
497  }
498 
499  // Traverse operations.
500  for (auto &op : bb) {
501  // Set the current debug location within the builder.
502  builder.SetCurrentDebugLocation(
503  debugTranslation->translateLoc(op.getLoc(), subprogram));
504 
505  if (failed(convertOperation(op, builder)))
506  return failure();
507  }
508 
509  return success();
510 }
511 
512 /// A helper method to get the single Block in an operation honoring LLVM's
513 /// module requirements.
514 static Block &getModuleBody(Operation *module) {
515  return module->getRegion(0).front();
516 }
517 
518 /// A helper method to decide if a constant must not be set as a global variable
519 /// initializer. For an external linkage variable, the variable with an
520 /// initializer is considered externally visible and defined in this module, the
521 /// variable without an initializer is externally available and is defined
522 /// elsewhere.
523 static bool shouldDropGlobalInitializer(llvm::GlobalValue::LinkageTypes linkage,
524  llvm::Constant *cst) {
525  return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
526  linkage == llvm::GlobalVariable::ExternalWeakLinkage;
527 }
528 
529 /// Sets the runtime preemption specifier of `gv` to dso_local if
530 /// `dsoLocalRequested` is true, otherwise it is left unchanged.
531 static void addRuntimePreemptionSpecifier(bool dsoLocalRequested,
532  llvm::GlobalValue *gv) {
533  if (dsoLocalRequested)
534  gv->setDSOLocal(true);
535 }
536 
537 /// Create named global variables that correspond to llvm.mlir.global
538 /// definitions. Convert llvm.global_ctors and global_dtors ops.
539 LogicalResult ModuleTranslation::convertGlobals() {
540  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
541  llvm::Type *type = convertType(op.getType());
542  llvm::Constant *cst = nullptr;
543  if (op.getValueOrNull()) {
544  // String attributes are treated separately because they cannot appear as
545  // in-function constants and are thus not supported by getLLVMConstant.
546  if (auto strAttr = op.getValueOrNull().dyn_cast_or_null<StringAttr>()) {
547  cst = llvm::ConstantDataArray::getString(
548  llvmModule->getContext(), strAttr.getValue(), /*AddNull=*/false);
549  type = cst->getType();
550  } else if (!(cst = getLLVMConstant(type, op.getValueOrNull(), op.getLoc(),
551  *this))) {
552  return failure();
553  }
554  }
555 
556  auto linkage = convertLinkageToLLVM(op.getLinkage());
557  auto addrSpace = op.getAddrSpace();
558 
559  // LLVM IR requires constant with linkage other than external or weak
560  // external to have initializers. If MLIR does not provide an initializer,
561  // default to undef.
562  bool dropInitializer = shouldDropGlobalInitializer(linkage, cst);
563  if (!dropInitializer && !cst)
564  cst = llvm::UndefValue::get(type);
565  else if (dropInitializer && cst)
566  cst = nullptr;
567 
568  auto *var = new llvm::GlobalVariable(
569  *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
570  /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal, addrSpace);
571 
572  if (op.getUnnamedAddr().hasValue())
573  var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
574 
575  if (op.getSection().hasValue())
576  var->setSection(*op.getSection());
577 
578  addRuntimePreemptionSpecifier(op.getDsoLocal(), var);
579 
580  Optional<uint64_t> alignment = op.getAlignment();
581  if (alignment.hasValue())
582  var->setAlignment(llvm::MaybeAlign(alignment.getValue()));
583 
584  globalsMapping.try_emplace(op, var);
585  }
586 
587  // Convert global variable bodies. This is done after all global variables
588  // have been created in LLVM IR because a global body may refer to another
589  // global or itself. So all global variables need to be mapped first.
590  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
591  if (Block *initializer = op.getInitializerBlock()) {
592  llvm::IRBuilder<> builder(llvmModule->getContext());
593  for (auto &op : initializer->without_terminator()) {
594  if (failed(convertOperation(op, builder)) ||
595  !isa<llvm::Constant>(lookupValue(op.getResult(0))))
596  return emitError(op.getLoc(), "unemittable constant value");
597  }
598  ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
599  llvm::Constant *cst =
600  cast<llvm::Constant>(lookupValue(ret.getOperand(0)));
601  auto *global = cast<llvm::GlobalVariable>(lookupGlobal(op));
602  if (!shouldDropGlobalInitializer(global->getLinkage(), cst))
603  global->setInitializer(cst);
604  }
605  }
606 
607  // Convert llvm.mlir.global_ctors and dtors.
608  for (Operation &op : getModuleBody(mlirModule)) {
609  auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
610  auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
611  if (!ctorOp && !dtorOp)
612  continue;
613  auto range = ctorOp ? llvm::zip(ctorOp.ctors(), ctorOp.priorities())
614  : llvm::zip(dtorOp.dtors(), dtorOp.priorities());
615  auto appendGlobalFn =
616  ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
617  for (auto symbolAndPriority : range) {
618  llvm::Function *f = lookupFunction(
619  std::get<0>(symbolAndPriority).cast<FlatSymbolRefAttr>().getValue());
620  appendGlobalFn(
621  *llvmModule.get(), f,
622  std::get<1>(symbolAndPriority).cast<IntegerAttr>().getInt(),
623  /*Data=*/nullptr);
624  }
625  }
626 
627  return success();
628 }
629 
630 /// Attempts to add an attribute identified by `key`, optionally with the given
631 /// `value` to LLVM function `llvmFunc`. Reports errors at `loc` if any. If the
632 /// attribute has a kind known to LLVM IR, create the attribute of this kind,
633 /// otherwise keep it as a string attribute. Performs additional checks for
634 /// attributes known to have or not have a value in order to avoid assertions
635 /// inside LLVM upon construction.
637  llvm::Function *llvmFunc,
638  StringRef key,
639  StringRef value = StringRef()) {
640  auto kind = llvm::Attribute::getAttrKindFromName(key);
641  if (kind == llvm::Attribute::None) {
642  llvmFunc->addFnAttr(key, value);
643  return success();
644  }
645 
646  if (llvm::Attribute::isIntAttrKind(kind)) {
647  if (value.empty())
648  return emitError(loc) << "LLVM attribute '" << key << "' expects a value";
649 
650  int result;
651  if (!value.getAsInteger(/*Radix=*/0, result))
652  llvmFunc->addFnAttr(
653  llvm::Attribute::get(llvmFunc->getContext(), kind, result));
654  else
655  llvmFunc->addFnAttr(key, value);
656  return success();
657  }
658 
659  if (!value.empty())
660  return emitError(loc) << "LLVM attribute '" << key
661  << "' does not expect a value, found '" << value
662  << "'";
663 
664  llvmFunc->addFnAttr(kind);
665  return success();
666 }
667 
668 /// Attaches the attributes listed in the given array attribute to `llvmFunc`.
669 /// Reports error to `loc` if any and returns immediately. Expects `attributes`
670 /// to be an array attribute containing either string attributes, treated as
671 /// value-less LLVM attributes, or array attributes containing two string
672 /// attributes, with the first string being the name of the corresponding LLVM
673 /// attribute and the second string beings its value. Note that even integer
674 /// attributes are expected to have their values expressed as strings.
675 static LogicalResult
677  llvm::Function *llvmFunc) {
678  if (!attributes)
679  return success();
680 
681  for (Attribute attr : *attributes) {
682  if (auto stringAttr = attr.dyn_cast<StringAttr>()) {
683  if (failed(
684  checkedAddLLVMFnAttribute(loc, llvmFunc, stringAttr.getValue())))
685  return failure();
686  continue;
687  }
688 
689  auto arrayAttr = attr.dyn_cast<ArrayAttr>();
690  if (!arrayAttr || arrayAttr.size() != 2)
691  return emitError(loc)
692  << "expected 'passthrough' to contain string or array attributes";
693 
694  auto keyAttr = arrayAttr[0].dyn_cast<StringAttr>();
695  auto valueAttr = arrayAttr[1].dyn_cast<StringAttr>();
696  if (!keyAttr || !valueAttr)
697  return emitError(loc)
698  << "expected arrays within 'passthrough' to contain two strings";
699 
700  if (failed(checkedAddLLVMFnAttribute(loc, llvmFunc, keyAttr.getValue(),
701  valueAttr.getValue())))
702  return failure();
703  }
704  return success();
705 }
706 
707 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
708  // Clear the block, branch value mappings, they are only relevant within one
709  // function.
710  blockMapping.clear();
711  valueMapping.clear();
712  branchMapping.clear();
713  llvm::Function *llvmFunc = lookupFunction(func.getName());
714 
715  // Translate the debug information for this function.
716  debugTranslation->translate(func, *llvmFunc);
717 
718  // Add function arguments to the value remapping table.
719  // If there was noalias info then we decorate each argument accordingly.
720  unsigned int argIdx = 0;
721  for (auto kvp : llvm::zip(func.getArguments(), llvmFunc->args())) {
722  llvm::Argument &llvmArg = std::get<1>(kvp);
723  BlockArgument mlirArg = std::get<0>(kvp);
724 
725  if (auto attr = func.getArgAttrOfType<UnitAttr>(
726  argIdx, LLVMDialect::getNoAliasAttrName())) {
727  // NB: Attribute already verified to be boolean, so check if we can indeed
728  // attach the attribute to this argument, based on its type.
729  auto argTy = mlirArg.getType();
730  if (!argTy.isa<LLVM::LLVMPointerType>())
731  return func.emitError(
732  "llvm.noalias attribute attached to LLVM non-pointer argument");
733  llvmArg.addAttr(llvm::Attribute::AttrKind::NoAlias);
734  }
735 
736  if (auto attr = func.getArgAttrOfType<IntegerAttr>(
737  argIdx, LLVMDialect::getAlignAttrName())) {
738  // NB: Attribute already verified to be int, so check if we can indeed
739  // attach the attribute to this argument, based on its type.
740  auto argTy = mlirArg.getType();
741  if (!argTy.isa<LLVM::LLVMPointerType>())
742  return func.emitError(
743  "llvm.align attribute attached to LLVM non-pointer argument");
744  llvmArg.addAttrs(
745  llvm::AttrBuilder().addAlignmentAttr(llvm::Align(attr.getInt())));
746  }
747 
748  if (auto attr = func.getArgAttrOfType<UnitAttr>(argIdx, "llvm.sret")) {
749  auto argTy = mlirArg.getType();
750  if (!argTy.isa<LLVM::LLVMPointerType>())
751  return func.emitError(
752  "llvm.sret attribute attached to LLVM non-pointer argument");
753  llvmArg.addAttrs(llvm::AttrBuilder().addStructRetAttr(
754  llvmArg.getType()->getPointerElementType()));
755  }
756 
757  if (auto attr = func.getArgAttrOfType<UnitAttr>(argIdx, "llvm.byval")) {
758  auto argTy = mlirArg.getType();
759  if (!argTy.isa<LLVM::LLVMPointerType>())
760  return func.emitError(
761  "llvm.byval attribute attached to LLVM non-pointer argument");
762  llvmArg.addAttrs(llvm::AttrBuilder().addByValAttr(
763  llvmArg.getType()->getPointerElementType()));
764  }
765 
766  mapValue(mlirArg, &llvmArg);
767  argIdx++;
768  }
769 
770  // Check the personality and set it.
771  if (func.getPersonality().hasValue()) {
772  llvm::Type *ty = llvm::Type::getInt8PtrTy(llvmFunc->getContext());
773  if (llvm::Constant *pfunc = getLLVMConstant(ty, func.getPersonalityAttr(),
774  func.getLoc(), *this))
775  llvmFunc->setPersonalityFn(pfunc);
776  }
777 
778  // First, create all blocks so we can jump to them.
779  llvm::LLVMContext &llvmContext = llvmFunc->getContext();
780  for (auto &bb : func) {
781  auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
782  llvmBB->insertInto(llvmFunc);
783  mapBlock(&bb, llvmBB);
784  }
785 
786  // Then, convert blocks one by one in topological order to ensure defs are
787  // converted before uses.
788  auto blocks = detail::getTopologicallySortedBlocks(func.getBody());
789  for (Block *bb : blocks) {
790  llvm::IRBuilder<> builder(llvmContext);
791  if (failed(convertBlock(*bb, bb->isEntryBlock(), builder)))
792  return failure();
793  }
794 
795  // After all blocks have been traversed and values mapped, connect the PHI
796  // nodes to the results of preceding blocks.
797  detail::connectPHINodes(func.getBody(), *this);
798 
799  // Finally, convert dialect attributes attached to the function.
800  return convertDialectAttributes(func);
801 }
802 
803 LogicalResult ModuleTranslation::convertDialectAttributes(Operation *op) {
804  for (NamedAttribute attribute : op->getDialectAttrs())
805  if (failed(iface.amendOperation(op, attribute, *this)))
806  return failure();
807  return success();
808 }
809 
810 LogicalResult ModuleTranslation::convertFunctionSignatures() {
811  // Declare all functions first because there may be function calls that form a
812  // call graph with cycles, or global initializers that reference functions.
813  for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
814  llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
815  function.getName(),
816  cast<llvm::FunctionType>(convertType(function.getType())));
817  llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
818  llvmFunc->setLinkage(convertLinkageToLLVM(function.getLinkage()));
819  mapFunction(function.getName(), llvmFunc);
820  addRuntimePreemptionSpecifier(function.getDsoLocal(), llvmFunc);
821 
822  // Forward the pass-through attributes to LLVM.
824  function.getLoc(), function.getPassthrough(), llvmFunc)))
825  return failure();
826  }
827 
828  return success();
829 }
830 
831 LogicalResult ModuleTranslation::convertFunctions() {
832  // Convert functions.
833  for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
834  // Ignore external functions.
835  if (function.isExternal())
836  continue;
837 
838  if (failed(convertOneFunction(function)))
839  return failure();
840  }
841 
842  return success();
843 }
844 
845 llvm::MDNode *
847  SymbolRefAttr accessGroupRef) const {
848  auto metadataName = accessGroupRef.getRootReference();
849  auto accessGroupName = accessGroupRef.getLeafReference();
850  auto metadataOp = SymbolTable::lookupNearestSymbolFrom<LLVM::MetadataOp>(
851  opInst.getParentOp(), metadataName);
852  auto *accessGroupOp =
853  SymbolTable::lookupNearestSymbolFrom(metadataOp, accessGroupName);
854  return accessGroupMetadataMapping.lookup(accessGroupOp);
855 }
856 
857 LogicalResult ModuleTranslation::createAccessGroupMetadata() {
858  mlirModule->walk([&](LLVM::MetadataOp metadatas) {
859  metadatas.walk([&](LLVM::AccessGroupMetadataOp op) {
860  llvm::LLVMContext &ctx = llvmModule->getContext();
861  llvm::MDNode *accessGroup = llvm::MDNode::getDistinct(ctx, {});
862  accessGroupMetadataMapping.insert({op, accessGroup});
863  });
864  });
865  return success();
866 }
867 
869  llvm::Instruction *inst) {
870  auto accessGroups =
871  op->getAttrOfType<ArrayAttr>(LLVMDialect::getAccessGroupsAttrName());
872  if (accessGroups && !accessGroups.empty()) {
873  llvm::Module *module = inst->getModule();
875  for (SymbolRefAttr accessGroupRef :
876  accessGroups.getAsRange<SymbolRefAttr>())
877  metadatas.push_back(getAccessGroup(*op, accessGroupRef));
878 
879  llvm::MDNode *unionMD = nullptr;
880  if (metadatas.size() == 1)
881  unionMD = llvm::cast<llvm::MDNode>(metadatas.front());
882  else if (metadatas.size() >= 2)
883  unionMD = llvm::MDNode::get(module->getContext(), metadatas);
884 
885  inst->setMetadata(module->getMDKindID("llvm.access.group"), unionMD);
886  }
887 }
888 
889 LogicalResult ModuleTranslation::createAliasScopeMetadata() {
890  mlirModule->walk([&](LLVM::MetadataOp metadatas) {
891  // Create the domains first, so they can be reference below in the scopes.
892  DenseMap<Operation *, llvm::MDNode *> aliasScopeDomainMetadataMapping;
893  metadatas.walk([&](LLVM::AliasScopeDomainMetadataOp op) {
894  llvm::LLVMContext &ctx = llvmModule->getContext();
896  operands.push_back({}); // Placeholder for self-reference
897  if (Optional<StringRef> description = op.getDescription())
898  operands.push_back(llvm::MDString::get(ctx, description.getValue()));
899  llvm::MDNode *domain = llvm::MDNode::get(ctx, operands);
900  domain->replaceOperandWith(0, domain); // Self-reference for uniqueness
901  aliasScopeDomainMetadataMapping.insert({op, domain});
902  });
903 
904  // Now create the scopes, referencing the domains created above.
905  metadatas.walk([&](LLVM::AliasScopeMetadataOp op) {
906  llvm::LLVMContext &ctx = llvmModule->getContext();
907  assert(isa<LLVM::MetadataOp>(op->getParentOp()));
908  auto metadataOp = dyn_cast<LLVM::MetadataOp>(op->getParentOp());
909  Operation *domainOp =
910  SymbolTable::lookupNearestSymbolFrom(metadataOp, op.getDomainAttr());
911  llvm::MDNode *domain = aliasScopeDomainMetadataMapping.lookup(domainOp);
912  assert(domain && "Scope's domain should already be valid");
914  operands.push_back({}); // Placeholder for self-reference
915  operands.push_back(domain);
916  if (Optional<StringRef> description = op.getDescription())
917  operands.push_back(llvm::MDString::get(ctx, description.getValue()));
918  llvm::MDNode *scope = llvm::MDNode::get(ctx, operands);
919  scope->replaceOperandWith(0, scope); // Self-reference for uniqueness
920  aliasScopeMetadataMapping.insert({op, scope});
921  });
922  });
923  return success();
924 }
925 
926 llvm::MDNode *
928  SymbolRefAttr aliasScopeRef) const {
929  StringAttr metadataName = aliasScopeRef.getRootReference();
930  StringAttr scopeName = aliasScopeRef.getLeafReference();
931  auto metadataOp = SymbolTable::lookupNearestSymbolFrom<LLVM::MetadataOp>(
932  opInst.getParentOp(), metadataName);
933  Operation *aliasScopeOp =
934  SymbolTable::lookupNearestSymbolFrom(metadataOp, scopeName);
935  return aliasScopeMetadataMapping.lookup(aliasScopeOp);
936 }
937 
939  llvm::Instruction *inst) {
940  auto populateScopeMetadata = [this, op, inst](StringRef attrName,
941  StringRef llvmMetadataName) {
942  auto scopes = op->getAttrOfType<ArrayAttr>(attrName);
943  if (!scopes || scopes.empty())
944  return;
945  llvm::Module *module = inst->getModule();
947  for (SymbolRefAttr scopeRef : scopes.getAsRange<SymbolRefAttr>())
948  scopeMDs.push_back(getAliasScope(*op, scopeRef));
949  llvm::MDNode *unionMD = llvm::MDNode::get(module->getContext(), scopeMDs);
950  inst->setMetadata(module->getMDKindID(llvmMetadataName), unionMD);
951  };
952 
953  populateScopeMetadata(LLVMDialect::getAliasScopesAttrName(), "alias.scope");
954  populateScopeMetadata(LLVMDialect::getNoAliasScopesAttrName(), "noalias");
955 }
956 
958  return typeTranslator.translateType(type);
959 }
960 
961 /// A helper to look up remapped operands in the value remapping table.
964  remapped.reserve(values.size());
965  for (Value v : values)
966  remapped.push_back(lookupValue(v));
967  return remapped;
968 }
969 
970 const llvm::DILocation *
971 ModuleTranslation::translateLoc(Location loc, llvm::DILocalScope *scope) {
972  return debugTranslation->translateLoc(loc, scope);
973 }
974 
975 llvm::NamedMDNode *
977  return llvmModule->getOrInsertNamedMetadata(name);
978 }
979 
980 void ModuleTranslation::StackFrame::anchor() {}
981 
982 static std::unique_ptr<llvm::Module>
983 prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
984  StringRef name) {
985  m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
986  auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
987  if (auto dataLayoutAttr =
988  m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName()))
989  llvmModule->setDataLayout(dataLayoutAttr.cast<StringAttr>().getValue());
990  if (auto targetTripleAttr =
991  m->getAttr(LLVM::LLVMDialect::getTargetTripleAttrName()))
992  llvmModule->setTargetTriple(targetTripleAttr.cast<StringAttr>().getValue());
993 
994  // Inject declarations for `malloc` and `free` functions that can be used in
995  // memref allocation/deallocation coming from standard ops lowering.
996  llvm::IRBuilder<> builder(llvmContext);
997  llvmModule->getOrInsertFunction("malloc", builder.getInt8PtrTy(),
998  builder.getInt64Ty());
999  llvmModule->getOrInsertFunction("free", builder.getVoidTy(),
1000  builder.getInt8PtrTy());
1001 
1002  return llvmModule;
1003 }
1004 
1005 std::unique_ptr<llvm::Module>
1006 mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
1007  StringRef name) {
1008  if (!satisfiesLLVMModule(module))
1009  return nullptr;
1010  std::unique_ptr<llvm::Module> llvmModule =
1011  prepareLLVMModule(module, llvmContext, name);
1012 
1014 
1015  ModuleTranslation translator(module, std::move(llvmModule));
1016  if (failed(translator.convertFunctionSignatures()))
1017  return nullptr;
1018  if (failed(translator.convertGlobals()))
1019  return nullptr;
1020  if (failed(translator.createAccessGroupMetadata()))
1021  return nullptr;
1022  if (failed(translator.createAliasScopeMetadata()))
1023  return nullptr;
1024  if (failed(translator.convertFunctions()))
1025  return nullptr;
1026 
1027  // Convert other top-level operations if possible.
1028  llvm::IRBuilder<> llvmBuilder(llvmContext);
1029  for (Operation &o : getModuleBody(module).getOperations()) {
1030  if (!isa<LLVM::LLVMFuncOp, LLVM::GlobalOp, LLVM::GlobalCtorsOp,
1031  LLVM::GlobalDtorsOp, LLVM::MetadataOp>(&o) &&
1032  !o.hasTrait<OpTrait::IsTerminator>() &&
1033  failed(translator.convertOperation(o, llvmBuilder))) {
1034  return nullptr;
1035  }
1036  }
1037 
1038  if (llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
1039  return nullptr;
1040 
1041  return std::move(translator.llvmModule);
1042 }
Include the generated interface declarations.
llvm::Constant * getLLVMConstant(llvm::Type *llvmType, Attribute attr, Location loc, const ModuleTranslation &moduleTranslation, bool isTopLevel=true)
Create an LLVM IR constant of llvmType from the MLIR attribute attr.
This class contains a list of basic blocks and a link to the parent operation it is attached to...
Definition: Region.h:26
U cast() const
Definition: Attributes.h:126
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
llvm::MDNode * getAliasScope(Operation &opInst, SymbolRefAttr aliasScopeRef) const
Returns the LLVM metadata corresponding to a reference to an mlir LLVM dialect alias scope operation...
Block represents an ordered list of Operations.
Definition: Block.h:29
Block & front()
Definition: Region.h:65
const llvm::DILocation * translateLoc(Location loc, llvm::DILocalScope *scope)
Translates the given location.
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::NamedMDNode * getOrInsertNamedModuleMetadata(StringRef name)
Gets the named metadata in the LLVM IR module being constructed, creating it if it does not exist...
A symbol reference with a reference path containing a single element.
static llvm::Type * getInnermostElementType(llvm::Type *type)
Returns the first non-sequential type nested in sequential types.
Value getOperand(unsigned idx)
Definition: Operation.h:219
AttrClass getAttrOfType(StringAttr name)
Definition: Operation.h:327
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
Definition: LogicalResult.h:72
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
iterator_range< pred_iterator > getPredecessors()
Definition: Block.h:226
ShapedType getType() const
Return the type of this ElementsAttr, guaranteed to be a vector or tensor with static shape...
void setAccessGroupsMetadata(Operation *op, llvm::Instruction *inst)
This class provides the API for ops that are known to be terminators.
Definition: OpDefinition.h:670
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
LogicalResult convertBlock(Block &bb, bool ignoreArguments, llvm::IRBuilderBase &builder)
Translates the contents of the given block to LLVM IR using this translator.
Operation & front()
Definition: Block.h:145
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
llvm::PointerUnion< NamedAttribute *, NamedTypeConstraint * > Argument
Definition: Argument.h:62
static constexpr const bool value
This is a common base class between Vector, UnrankedTensor, RankedTensor, and MemRef types because th...
Definition: BuiltinTypes.h:66
void forgetMapping(Region &region)
Removes the mapping for blocks contained in the region and values defined in these blocks...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:48
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:140
llvm::Value * 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.
Implementation class for module translation.
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:99
static LogicalResult forwardPassthroughAttributes(Location loc, Optional< ArrayAttr > attributes, llvm::Function *llvmFunc)
Attaches the attributes listed in the given array attribute to llvmFunc.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
static LogicalResult checkedAddLLVMFnAttribute(Location loc, llvm::Function *llvmFunc, StringRef key, StringRef value=StringRef())
Attempts to add an attribute identified by key, optionally with the given value to LLVM function llvm...
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:486
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...
iterator begin()
Definition: Region.h:55
An attribute that represents a reference to a dense vector or tensor object.
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...
Base class for dialect interfaces providing translation to LLVM IR.
llvm::Instruction * lookupBranch(Operation *op) const
Finds an LLVM IR instruction that corresponds to the given MLIR operation with successors.
U dyn_cast() const
Definition: Types.h:244
unsigned getNumArguments()
Definition: Block.h:120
ArrayRef< char > getRawData() const
Return the raw storage data held by this attribute.
Attributes are known-constant values of operations.
Definition: Attributes.h:27
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:117
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:206
OpResult getResult(unsigned idx)
Get the &#39;idx&#39;th result of this operation.
Definition: Operation.h:276
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:106
static void addRuntimePreemptionSpecifier(bool dsoLocalRequested, llvm::GlobalValue *gv)
Sets the runtime preemption specifier of gv to dso_local if dsoLocalRequested is true, otherwise it is left unchanged.
BlockArgListType getArguments()
Definition: Block.h:76
This class represents an argument of a Block.
Definition: Value.h:300
static Block & getModuleBody(Operation *module)
A helper method to get the single Block in an operation honoring LLVM&#39;s module requirements.
Tensor types represent multi-dimensional arrays, and have two variants: RankedTensorType and Unranked...
Definition: BuiltinTypes.h:152
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...
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
void setAliasScopeMetadata(Operation *op, llvm::Instruction *inst)
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
This class implements the successor iterators for Block.
Definition: BlockSupport.h:72
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:72
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of...
static std::unique_ptr< llvm::Module > prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext, StringRef name)
void connectPHINodes(Region &region, const ModuleTranslation &state)
For all blocks in the region that were converted to LLVM IR using the given ModuleTranslation, connect the PHI nodes of the corresponding LLVM IR blocks to the results of preceding blocks.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:84
An attribute that represents a reference to a splat vector or tensor constant, meaning all of the ele...
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...
Type getElementType() const
Return the element type.
Operation * getTerminator()
Get the terminator operation of this block.
Definition: Block.cpp:257
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
Definition: MLIRContext.h:92
SuccessorRange getSuccessors()
Definition: Operation.h:446
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
Type getType() const
Return the type of this value.
Definition: Value.h:119
iterator end()
Definition: Region.h:56
U dyn_cast() const
Definition: Attributes.h:120
llvm::MDNode * getAccessGroup(Operation &opInst, SymbolRefAttr accessGroupRef) const
Returns the LLVM metadata corresponding to a reference to an mlir LLVM dialect access group operation...
SetVector< Block * > getTopologicallySortedBlocks(Region &region)
Get a topologically sorted list of blocks of the given region.
std::unique_ptr< llvm::Module > translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext, llvm::StringRef name="LLVMDialectModule")
Translate operation that satisfies LLVM dialect module requirements into an LLVM IR module living in ...
LLVM dialect pointer type.
Definition: LLVMTypes.h:158
int64_t getNumElements() const
Returns the number of elements held by this attribute.
dialect_attr_range getDialectAttrs()
Return a range corresponding to the dialect attributes for this operation.
Definition: Operation.h:390
void ensureDistinctSuccessors(Operation *op)
Make argument-taking successors of each block distinct.
OperationName getName()
The name of an operation is the key identifier for it.
Definition: Operation.h:57
bool isa() const
Definition: Types.h:234
bool isSplat() const
Returns true if this attribute corresponds to a splat, i.e.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:231
int64_t getNumElements() const
If it has static shape, return the number of elements. Otherwise, abort.
std::enable_if<!std::is_base_of< Attribute, T >::value||std::is_same< Attribute, T >::value, T >::type getSplatValue() const
Return the splat value for this attribute.
This class provides an abstraction over the different types of ranges over Values.
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Definition: Operation.h:323
Region & getRegion(unsigned index)
Returns the region held by this operation at position &#39;index&#39;.
Definition: Operation.h:429
ArrayRef< int64_t > getShape() const
If this is a ranked type, return the shape. Otherwise, abort.
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.