MLIR  15.0.0git
LLVMToLLVMIRTranslation.cpp
Go to the documentation of this file.
1 //===- LLVMToLLVMIRTranslation.cpp - Translate LLVM dialect to LLVM IR ----===//
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 a translation between the MLIR LLVM dialect and LLVM IR.
10 //
11 //===----------------------------------------------------------------------===//
12 
15 #include "mlir/IR/Operation.h"
16 #include "mlir/Support/LLVM.h"
18 
19 #include "llvm/IR/IRBuilder.h"
20 #include "llvm/IR/InlineAsm.h"
21 #include "llvm/IR/MDBuilder.h"
22 #include "llvm/IR/MatrixBuilder.h"
23 #include "llvm/IR/Operator.h"
24 
25 using namespace mlir;
26 using namespace mlir::LLVM;
28 
29 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
30 
31 /// Convert MLIR integer comparison predicate to LLVM IR comparison predicate.
32 static llvm::CmpInst::Predicate getLLVMCmpPredicate(ICmpPredicate p) {
33  switch (p) {
34  case LLVM::ICmpPredicate::eq:
35  return llvm::CmpInst::Predicate::ICMP_EQ;
36  case LLVM::ICmpPredicate::ne:
37  return llvm::CmpInst::Predicate::ICMP_NE;
38  case LLVM::ICmpPredicate::slt:
39  return llvm::CmpInst::Predicate::ICMP_SLT;
40  case LLVM::ICmpPredicate::sle:
41  return llvm::CmpInst::Predicate::ICMP_SLE;
42  case LLVM::ICmpPredicate::sgt:
43  return llvm::CmpInst::Predicate::ICMP_SGT;
44  case LLVM::ICmpPredicate::sge:
45  return llvm::CmpInst::Predicate::ICMP_SGE;
46  case LLVM::ICmpPredicate::ult:
47  return llvm::CmpInst::Predicate::ICMP_ULT;
48  case LLVM::ICmpPredicate::ule:
49  return llvm::CmpInst::Predicate::ICMP_ULE;
50  case LLVM::ICmpPredicate::ugt:
51  return llvm::CmpInst::Predicate::ICMP_UGT;
52  case LLVM::ICmpPredicate::uge:
53  return llvm::CmpInst::Predicate::ICMP_UGE;
54  }
55  llvm_unreachable("incorrect comparison predicate");
56 }
57 
58 static llvm::CmpInst::Predicate getLLVMCmpPredicate(FCmpPredicate p) {
59  switch (p) {
60  case LLVM::FCmpPredicate::_false:
61  return llvm::CmpInst::Predicate::FCMP_FALSE;
62  case LLVM::FCmpPredicate::oeq:
63  return llvm::CmpInst::Predicate::FCMP_OEQ;
64  case LLVM::FCmpPredicate::ogt:
65  return llvm::CmpInst::Predicate::FCMP_OGT;
66  case LLVM::FCmpPredicate::oge:
67  return llvm::CmpInst::Predicate::FCMP_OGE;
68  case LLVM::FCmpPredicate::olt:
69  return llvm::CmpInst::Predicate::FCMP_OLT;
70  case LLVM::FCmpPredicate::ole:
71  return llvm::CmpInst::Predicate::FCMP_OLE;
72  case LLVM::FCmpPredicate::one:
73  return llvm::CmpInst::Predicate::FCMP_ONE;
74  case LLVM::FCmpPredicate::ord:
75  return llvm::CmpInst::Predicate::FCMP_ORD;
76  case LLVM::FCmpPredicate::ueq:
77  return llvm::CmpInst::Predicate::FCMP_UEQ;
78  case LLVM::FCmpPredicate::ugt:
79  return llvm::CmpInst::Predicate::FCMP_UGT;
80  case LLVM::FCmpPredicate::uge:
81  return llvm::CmpInst::Predicate::FCMP_UGE;
82  case LLVM::FCmpPredicate::ult:
83  return llvm::CmpInst::Predicate::FCMP_ULT;
84  case LLVM::FCmpPredicate::ule:
85  return llvm::CmpInst::Predicate::FCMP_ULE;
86  case LLVM::FCmpPredicate::une:
87  return llvm::CmpInst::Predicate::FCMP_UNE;
88  case LLVM::FCmpPredicate::uno:
89  return llvm::CmpInst::Predicate::FCMP_UNO;
90  case LLVM::FCmpPredicate::_true:
91  return llvm::CmpInst::Predicate::FCMP_TRUE;
92  }
93  llvm_unreachable("incorrect comparison predicate");
94 }
95 
96 static llvm::AtomicRMWInst::BinOp getLLVMAtomicBinOp(AtomicBinOp op) {
97  switch (op) {
98  case LLVM::AtomicBinOp::xchg:
99  return llvm::AtomicRMWInst::BinOp::Xchg;
100  case LLVM::AtomicBinOp::add:
101  return llvm::AtomicRMWInst::BinOp::Add;
102  case LLVM::AtomicBinOp::sub:
103  return llvm::AtomicRMWInst::BinOp::Sub;
104  case LLVM::AtomicBinOp::_and:
105  return llvm::AtomicRMWInst::BinOp::And;
106  case LLVM::AtomicBinOp::nand:
107  return llvm::AtomicRMWInst::BinOp::Nand;
108  case LLVM::AtomicBinOp::_or:
109  return llvm::AtomicRMWInst::BinOp::Or;
110  case LLVM::AtomicBinOp::_xor:
111  return llvm::AtomicRMWInst::BinOp::Xor;
113  return llvm::AtomicRMWInst::BinOp::Max;
115  return llvm::AtomicRMWInst::BinOp::Min;
116  case LLVM::AtomicBinOp::umax:
117  return llvm::AtomicRMWInst::BinOp::UMax;
118  case LLVM::AtomicBinOp::umin:
119  return llvm::AtomicRMWInst::BinOp::UMin;
120  case LLVM::AtomicBinOp::fadd:
121  return llvm::AtomicRMWInst::BinOp::FAdd;
122  case LLVM::AtomicBinOp::fsub:
123  return llvm::AtomicRMWInst::BinOp::FSub;
124  }
125  llvm_unreachable("incorrect atomic binary operator");
126 }
127 
128 static llvm::AtomicOrdering getLLVMAtomicOrdering(AtomicOrdering ordering) {
129  switch (ordering) {
130  case LLVM::AtomicOrdering::not_atomic:
131  return llvm::AtomicOrdering::NotAtomic;
132  case LLVM::AtomicOrdering::unordered:
133  return llvm::AtomicOrdering::Unordered;
134  case LLVM::AtomicOrdering::monotonic:
135  return llvm::AtomicOrdering::Monotonic;
136  case LLVM::AtomicOrdering::acquire:
137  return llvm::AtomicOrdering::Acquire;
138  case LLVM::AtomicOrdering::release:
139  return llvm::AtomicOrdering::Release;
140  case LLVM::AtomicOrdering::acq_rel:
141  return llvm::AtomicOrdering::AcquireRelease;
142  case LLVM::AtomicOrdering::seq_cst:
143  return llvm::AtomicOrdering::SequentiallyConsistent;
144  }
145  llvm_unreachable("incorrect atomic ordering");
146 }
147 
148 static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op) {
149  using llvmFMF = llvm::FastMathFlags;
150  using FuncT = void (llvmFMF::*)(bool);
151  const std::pair<FastmathFlags, FuncT> handlers[] = {
152  // clang-format off
153  {FastmathFlags::nnan, &llvmFMF::setNoNaNs},
154  {FastmathFlags::ninf, &llvmFMF::setNoInfs},
155  {FastmathFlags::nsz, &llvmFMF::setNoSignedZeros},
156  {FastmathFlags::arcp, &llvmFMF::setAllowReciprocal},
157  {FastmathFlags::contract, &llvmFMF::setAllowContract},
158  {FastmathFlags::afn, &llvmFMF::setApproxFunc},
159  {FastmathFlags::reassoc, &llvmFMF::setAllowReassoc},
160  // clang-format on
161  };
162  llvm::FastMathFlags ret;
163  auto fmf = op.getFastmathFlags();
164  for (auto it : handlers)
165  if (bitEnumContains(fmf, it.first))
166  (ret.*(it.second))(true);
167  return ret;
168 }
169 
170 /// Returns an LLVM metadata node corresponding to a loop option. This metadata
171 /// is attached to an llvm.loop node.
172 static llvm::MDNode *getLoopOptionMetadata(llvm::LLVMContext &ctx,
173  LoopOptionCase option,
174  int64_t value) {
175  StringRef name;
176  llvm::Constant *cstValue = nullptr;
177  switch (option) {
178  case LoopOptionCase::disable_licm:
179  name = "llvm.licm.disable";
180  cstValue = llvm::ConstantInt::getBool(ctx, value);
181  break;
182  case LoopOptionCase::disable_unroll:
183  name = "llvm.loop.unroll.disable";
184  cstValue = llvm::ConstantInt::getBool(ctx, value);
185  break;
186  case LoopOptionCase::interleave_count:
187  name = "llvm.loop.interleave.count";
188  cstValue = llvm::ConstantInt::get(
189  llvm::IntegerType::get(ctx, /*NumBits=*/32), value);
190  break;
191  case LoopOptionCase::disable_pipeline:
192  name = "llvm.loop.pipeline.disable";
193  cstValue = llvm::ConstantInt::getBool(ctx, value);
194  break;
195  case LoopOptionCase::pipeline_initiation_interval:
196  name = "llvm.loop.pipeline.initiationinterval";
197  cstValue = llvm::ConstantInt::get(
198  llvm::IntegerType::get(ctx, /*NumBits=*/32), value);
199  break;
200  }
201  return llvm::MDNode::get(ctx, {llvm::MDString::get(ctx, name),
202  llvm::ConstantAsMetadata::get(cstValue)});
203 }
204 
205 static void setLoopMetadata(Operation &opInst, llvm::Instruction &llvmInst,
206  llvm::IRBuilderBase &builder,
207  LLVM::ModuleTranslation &moduleTranslation) {
208  if (Attribute attr = opInst.getAttr(LLVMDialect::getLoopAttrName())) {
209  llvm::Module *module = builder.GetInsertBlock()->getModule();
210  llvm::MDNode *loopMD = moduleTranslation.lookupLoopOptionsMetadata(attr);
211  if (!loopMD) {
212  llvm::LLVMContext &ctx = module->getContext();
213 
214  SmallVector<llvm::Metadata *> loopOptions;
215  // Reserve operand 0 for loop id self reference.
216  auto dummy = llvm::MDNode::getTemporary(ctx, llvm::None);
217  loopOptions.push_back(dummy.get());
218 
219  auto loopAttr = attr.cast<DictionaryAttr>();
220  auto parallelAccessGroup =
221  loopAttr.getNamed(LLVMDialect::getParallelAccessAttrName());
222  if (parallelAccessGroup.hasValue()) {
223  SmallVector<llvm::Metadata *> parallelAccess;
224  parallelAccess.push_back(
225  llvm::MDString::get(ctx, "llvm.loop.parallel_accesses"));
226  for (SymbolRefAttr accessGroupRef : parallelAccessGroup->getValue()
227  .cast<ArrayAttr>()
228  .getAsRange<SymbolRefAttr>())
229  parallelAccess.push_back(
230  moduleTranslation.getAccessGroup(opInst, accessGroupRef));
231  loopOptions.push_back(llvm::MDNode::get(ctx, parallelAccess));
232  }
233 
234  if (auto loopOptionsAttr = loopAttr.getAs<LoopOptionsAttr>(
235  LLVMDialect::getLoopOptionsAttrName())) {
236  for (auto option : loopOptionsAttr.getOptions())
237  loopOptions.push_back(
238  getLoopOptionMetadata(ctx, option.first, option.second));
239  }
240 
241  // Create loop options and set the first operand to itself.
242  loopMD = llvm::MDNode::get(ctx, loopOptions);
243  loopMD->replaceOperandWith(0, loopMD);
244 
245  // Store a map from this Attribute to the LLVM metadata in case we
246  // encounter it again.
247  moduleTranslation.mapLoopOptionsMetadata(attr, loopMD);
248  }
249 
250  llvmInst.setMetadata(module->getMDKindID("llvm.loop"), loopMD);
251  }
252 }
253 
254 static LogicalResult
255 convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
256  LLVM::ModuleTranslation &moduleTranslation) {
257  auto extractPosition = [](ArrayAttr attr) {
258  SmallVector<unsigned, 4> position;
259  position.reserve(attr.size());
260  for (Attribute v : attr)
261  position.push_back(v.cast<IntegerAttr>().getValue().getZExtValue());
262  return position;
263  };
264 
265  llvm::IRBuilder<>::FastMathFlagGuard fmfGuard(builder);
266  if (auto fmf = dyn_cast<FastmathFlagsInterface>(opInst))
267  builder.setFastMathFlags(getFastmathFlags(fmf));
268 
269 #include "mlir/Dialect/LLVMIR/LLVMConversions.inc"
270 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicConversions.inc"
271 
272  // Emit function calls. If the "callee" attribute is present, this is a
273  // direct function call and we also need to look up the remapped function
274  // itself. Otherwise, this is an indirect call and the callee is the first
275  // operand, look it up as a normal value. Return the llvm::Value representing
276  // the function result, which may be of llvm::VoidTy type.
277  auto convertCall = [&](Operation &op) -> llvm::Value * {
278  auto operands = moduleTranslation.lookupValues(op.getOperands());
279  ArrayRef<llvm::Value *> operandsRef(operands);
280  if (auto attr = op.getAttrOfType<FlatSymbolRefAttr>("callee"))
281  return builder.CreateCall(
282  moduleTranslation.lookupFunction(attr.getValue()), operandsRef);
283  auto calleeType =
284  op.getOperands().front().getType().cast<LLVMPointerType>();
285  auto *calleeFunctionType = cast<llvm::FunctionType>(
286  moduleTranslation.convertType(calleeType.getElementType()));
287  return builder.CreateCall(calleeFunctionType, operandsRef.front(),
288  operandsRef.drop_front());
289  };
290 
291  // Emit calls. If the called function has a result, remap the corresponding
292  // value. Note that LLVM IR dialect CallOp has either 0 or 1 result.
293  if (isa<LLVM::CallOp>(opInst)) {
294  llvm::Value *result = convertCall(opInst);
295  if (opInst.getNumResults() != 0) {
296  moduleTranslation.mapValue(opInst.getResult(0), result);
297  return success();
298  }
299  // Check that LLVM call returns void for 0-result functions.
300  return success(result->getType()->isVoidTy());
301  }
302 
303  if (auto inlineAsmOp = dyn_cast<LLVM::InlineAsmOp>(opInst)) {
304  // TODO: refactor function type creation which usually occurs in std-LLVM
305  // conversion.
306  SmallVector<Type, 8> operandTypes;
307  llvm::append_range(operandTypes, inlineAsmOp.getOperands().getTypes());
308 
309  Type resultType;
310  if (inlineAsmOp.getNumResults() == 0) {
311  resultType = LLVM::LLVMVoidType::get(&moduleTranslation.getContext());
312  } else {
313  assert(inlineAsmOp.getNumResults() == 1);
314  resultType = inlineAsmOp.getResultTypes()[0];
315  }
316  auto ft = LLVM::LLVMFunctionType::get(resultType, operandTypes);
317  llvm::InlineAsm *inlineAsmInst =
318  inlineAsmOp.getAsmDialect().hasValue()
319  ? llvm::InlineAsm::get(
320  static_cast<llvm::FunctionType *>(
321  moduleTranslation.convertType(ft)),
322  inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
323  inlineAsmOp.getHasSideEffects(),
324  inlineAsmOp.getIsAlignStack(),
325  convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
326  : llvm::InlineAsm::get(static_cast<llvm::FunctionType *>(
327  moduleTranslation.convertType(ft)),
328  inlineAsmOp.getAsmString(),
329  inlineAsmOp.getConstraints(),
330  inlineAsmOp.getHasSideEffects(),
331  inlineAsmOp.getIsAlignStack());
332  llvm::CallInst *inst = builder.CreateCall(
333  inlineAsmInst,
334  moduleTranslation.lookupValues(inlineAsmOp.getOperands()));
335  if (auto maybeOperandAttrs = inlineAsmOp.getOperandAttrs()) {
336  llvm::AttributeList attrList;
337  for (const auto &it : llvm::enumerate(*maybeOperandAttrs)) {
338  Attribute attr = it.value();
339  if (!attr)
340  continue;
341  DictionaryAttr dAttr = attr.cast<DictionaryAttr>();
342  TypeAttr tAttr =
343  dAttr.get(InlineAsmOp::getElementTypeAttrName()).cast<TypeAttr>();
344  llvm::AttrBuilder b(moduleTranslation.getLLVMContext());
345  llvm::Type *ty = moduleTranslation.convertType(tAttr.getValue());
346  b.addTypeAttr(llvm::Attribute::ElementType, ty);
347  // shift to account for the returned value (this is always 1 aggregate
348  // value in LLVM).
349  int shift = (opInst.getNumResults() > 0) ? 1 : 0;
350  attrList = attrList.addAttributesAtIndex(
351  moduleTranslation.getLLVMContext(), it.index() + shift, b);
352  }
353  inst->setAttributes(attrList);
354  }
355 
356  if (opInst.getNumResults() != 0)
357  moduleTranslation.mapValue(opInst.getResult(0), inst);
358  return success();
359  }
360 
361  if (auto invOp = dyn_cast<LLVM::InvokeOp>(opInst)) {
362  auto operands = moduleTranslation.lookupValues(invOp.getCalleeOperands());
363  ArrayRef<llvm::Value *> operandsRef(operands);
364  llvm::Instruction *result;
365  if (auto attr = opInst.getAttrOfType<FlatSymbolRefAttr>("callee")) {
366  result = builder.CreateInvoke(
367  moduleTranslation.lookupFunction(attr.getValue()),
368  moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
369  moduleTranslation.lookupBlock(invOp.getSuccessor(1)), operandsRef);
370  } else {
371  auto calleeType =
372  invOp.getCalleeOperands().front().getType().cast<LLVMPointerType>();
373  auto *calleeFunctionType = cast<llvm::FunctionType>(
374  moduleTranslation.convertType(calleeType.getElementType()));
375  result = builder.CreateInvoke(
376  calleeFunctionType, operandsRef.front(),
377  moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
378  moduleTranslation.lookupBlock(invOp.getSuccessor(1)),
379  operandsRef.drop_front());
380  }
381  moduleTranslation.mapBranch(invOp, result);
382  // InvokeOp can only have 0 or 1 result
383  if (invOp->getNumResults() != 0) {
384  moduleTranslation.mapValue(opInst.getResult(0), result);
385  return success();
386  }
387  return success(result->getType()->isVoidTy());
388  }
389 
390  if (auto lpOp = dyn_cast<LLVM::LandingpadOp>(opInst)) {
391  llvm::Type *ty = moduleTranslation.convertType(lpOp.getType());
392  llvm::LandingPadInst *lpi =
393  builder.CreateLandingPad(ty, lpOp.getNumOperands());
394  lpi->setCleanup(lpOp.getCleanup());
395 
396  // Add clauses
397  for (llvm::Value *operand :
398  moduleTranslation.lookupValues(lpOp.getOperands())) {
399  // All operands should be constant - checked by verifier
400  if (auto *constOperand = dyn_cast<llvm::Constant>(operand))
401  lpi->addClause(constOperand);
402  }
403  moduleTranslation.mapValue(lpOp.getResult(), lpi);
404  return success();
405  }
406 
407  // Emit branches. We need to look up the remapped blocks and ignore the block
408  // arguments that were transformed into PHI nodes.
409  if (auto brOp = dyn_cast<LLVM::BrOp>(opInst)) {
410  llvm::BranchInst *branch =
411  builder.CreateBr(moduleTranslation.lookupBlock(brOp.getSuccessor()));
412  moduleTranslation.mapBranch(&opInst, branch);
413  setLoopMetadata(opInst, *branch, builder, moduleTranslation);
414  return success();
415  }
416  if (auto condbrOp = dyn_cast<LLVM::CondBrOp>(opInst)) {
417  llvm::MDNode *branchWeights = nullptr;
418  if (auto weights = condbrOp.getBranchWeights()) {
419  // Map weight attributes to LLVM metadata.
420  auto weightValues = weights->getValues<APInt>();
421  auto trueWeight = weightValues[0].getSExtValue();
422  auto falseWeight = weightValues[1].getSExtValue();
423  branchWeights =
424  llvm::MDBuilder(moduleTranslation.getLLVMContext())
425  .createBranchWeights(static_cast<uint32_t>(trueWeight),
426  static_cast<uint32_t>(falseWeight));
427  }
428  llvm::BranchInst *branch = builder.CreateCondBr(
429  moduleTranslation.lookupValue(condbrOp.getOperand(0)),
430  moduleTranslation.lookupBlock(condbrOp.getSuccessor(0)),
431  moduleTranslation.lookupBlock(condbrOp.getSuccessor(1)), branchWeights);
432  moduleTranslation.mapBranch(&opInst, branch);
433  setLoopMetadata(opInst, *branch, builder, moduleTranslation);
434  return success();
435  }
436  if (auto switchOp = dyn_cast<LLVM::SwitchOp>(opInst)) {
437  llvm::MDNode *branchWeights = nullptr;
438  if (auto weights = switchOp.getBranchWeights()) {
439  llvm::SmallVector<uint32_t> weightValues;
440  weightValues.reserve(weights->size());
441  for (llvm::APInt weight : weights->cast<DenseIntElementsAttr>())
442  weightValues.push_back(weight.getLimitedValue());
443  branchWeights = llvm::MDBuilder(moduleTranslation.getLLVMContext())
444  .createBranchWeights(weightValues);
445  }
446 
447  llvm::SwitchInst *switchInst = builder.CreateSwitch(
448  moduleTranslation.lookupValue(switchOp.getValue()),
449  moduleTranslation.lookupBlock(switchOp.getDefaultDestination()),
450  switchOp.getCaseDestinations().size(), branchWeights);
451 
452  auto *ty = llvm::cast<llvm::IntegerType>(
453  moduleTranslation.convertType(switchOp.getValue().getType()));
454  for (auto i :
455  llvm::zip(switchOp.getCaseValues()->cast<DenseIntElementsAttr>(),
456  switchOp.getCaseDestinations()))
457  switchInst->addCase(
458  llvm::ConstantInt::get(ty, std::get<0>(i).getLimitedValue()),
459  moduleTranslation.lookupBlock(std::get<1>(i)));
460 
461  moduleTranslation.mapBranch(&opInst, switchInst);
462  return success();
463  }
464 
465  // Emit addressof. We need to look up the global value referenced by the
466  // operation and store it in the MLIR-to-LLVM value mapping. This does not
467  // emit any LLVM instruction.
468  if (auto addressOfOp = dyn_cast<LLVM::AddressOfOp>(opInst)) {
469  LLVM::GlobalOp global = addressOfOp.getGlobal();
470  LLVM::LLVMFuncOp function = addressOfOp.getFunction();
471 
472  // The verifier should not have allowed this.
473  assert((global || function) &&
474  "referencing an undefined global or function");
475 
476  moduleTranslation.mapValue(
477  addressOfOp.getResult(),
478  global ? moduleTranslation.lookupGlobal(global)
479  : moduleTranslation.lookupFunction(function.getName()));
480  return success();
481  }
482 
483  return failure();
484 }
485 
486 namespace {
487 /// Implementation of the dialect interface that converts operations belonging
488 /// to the LLVM dialect to LLVM IR.
489 class LLVMDialectLLVMIRTranslationInterface
491 public:
493 
494  /// Translates the given operation to LLVM IR using the provided IR builder
495  /// and saving the state in `moduleTranslation`.
497  convertOperation(Operation *op, llvm::IRBuilderBase &builder,
498  LLVM::ModuleTranslation &moduleTranslation) const final {
499  return convertOperationImpl(*op, builder, moduleTranslation);
500  }
501 };
502 } // namespace
503 
505  registry.insert<LLVM::LLVMDialect>();
506  registry.addExtension(+[](MLIRContext *ctx, LLVM::LLVMDialect *dialect) {
507  dialect->addInterfaces<LLVMDialectLLVMIRTranslationInterface>();
508  });
509 }
510 
512  DialectRegistry registry;
514  context.appendDialectRegistry(registry);
515 }
Include the generated interface declarations.
U cast() const
Definition: Attributes.h:130
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
A symbol reference with a reference path containing a single element.
static llvm::MDNode * getLoopOptionMetadata(llvm::LLVMContext &ctx, LoopOptionCase option, int64_t value)
Returns an LLVM metadata node corresponding to a loop option.
AttrClass getAttrOfType(StringAttr name)
Definition: Operation.h:382
void appendDialectRegistry(const DialectRegistry &registry)
Append the contents of the given dialect registry to the registry associated with this context...
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
static LogicalResult convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void setLoopMetadata(Operation &opInst, llvm::Instruction &llvmInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
void mapLoopOptionsMetadata(Attribute options, llvm::MDNode *metadata)
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
static llvm::AtomicRMWInst::BinOp getLLVMAtomicBinOp(AtomicBinOp op)
static LLVMFunctionType get(Type result, ArrayRef< Type > arguments, bool isVarArg=false)
Gets or creates an instance of LLVM dialect function in the same context as the result type...
Definition: LLVMTypes.cpp:101
static constexpr const bool value
Implementation class for module translation.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
void addExtension(std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
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
void mapValue(Value mlir, llvm::Value *llvm)
Stores the mapping between an MLIR value and its LLVM IR counterpart.
Base class for dialect interfaces providing translation to LLVM IR.
MLIRContext & getContext()
Returns the MLIR context of the module being translated.
Attributes are known-constant values of operations.
Definition: Attributes.h:24
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:234
static llvm::CmpInst::Predicate getLLVMCmpPredicate(ICmpPredicate p)
Convert MLIR integer comparison predicate to LLVM IR comparison predicate.
OpResult getResult(unsigned idx)
Get the &#39;idx&#39;th result of this operation.
Definition: Operation.h:331
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:72
void registerLLVMDialectTranslation(DialectRegistry &registry)
Register the LLVM dialect and the translation from it to the LLVM IR in the given registry;...
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op)
void mapBranch(Operation *mlir, llvm::Instruction *llvm)
Stores the mapping between an MLIR operation with successors and a corresponding LLVM IR instruction...
llvm::MDNode * getAccessGroup(Operation &opInst, SymbolRefAttr accessGroupRef) const
Returns the LLVM metadata corresponding to a reference to an mlir LLVM dialect access group operation...
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value...
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
static void contract(RootOrderingGraph &graph, ArrayRef< Value > cycle, const DenseMap< Value, unsigned > &parentDepths, DenseMap< Value, Value > &actualSource, DenseMap< Value, Value > &actualTarget)
Contracts the specified cycle in the given graph in-place.
LLVM dialect pointer type.
Definition: LLVMTypes.h:182
unsigned getNumResults()
Return the number of results held by this operation.
Definition: Operation.h:328
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.
llvm::MDNode * lookupLoopOptionsMetadata(Attribute options) const
Returns the LLVM metadata corresponding to a llvm loop&#39;s codegen options attribute.
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Definition: Operation.h:378
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static llvm::AtomicOrdering getLLVMAtomicOrdering(AtomicOrdering ordering)
An attribute that represents a reference to a dense integer vector or tensor object.