MLIR  22.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"
17 #include "mlir/Support/LLVM.h"
19 
20 #include "llvm/ADT/TypeSwitch.h"
21 #include "llvm/IR/DIBuilder.h"
22 #include "llvm/IR/IRBuilder.h"
23 #include "llvm/IR/InlineAsm.h"
24 #include "llvm/IR/Instructions.h"
25 #include "llvm/IR/MDBuilder.h"
26 #include "llvm/IR/MatrixBuilder.h"
27 #include "llvm/IR/MemoryModelRelaxationAnnotations.h"
28 #include "llvm/Support/LogicalResult.h"
29 
30 using namespace mlir;
31 using namespace mlir::LLVM;
33 
34 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
35 
36 static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op) {
37  using llvmFMF = llvm::FastMathFlags;
38  using FuncT = void (llvmFMF::*)(bool);
39  const std::pair<FastmathFlags, FuncT> handlers[] = {
40  // clang-format off
41  {FastmathFlags::nnan, &llvmFMF::setNoNaNs},
42  {FastmathFlags::ninf, &llvmFMF::setNoInfs},
43  {FastmathFlags::nsz, &llvmFMF::setNoSignedZeros},
44  {FastmathFlags::arcp, &llvmFMF::setAllowReciprocal},
45  {FastmathFlags::contract, &llvmFMF::setAllowContract},
46  {FastmathFlags::afn, &llvmFMF::setApproxFunc},
47  {FastmathFlags::reassoc, &llvmFMF::setAllowReassoc},
48  // clang-format on
49  };
50  llvm::FastMathFlags ret;
51  ::mlir::LLVM::FastmathFlags fmfMlir = op.getFastmathAttr().getValue();
52  for (auto it : handlers)
53  if (bitEnumContainsAll(fmfMlir, it.first))
54  (ret.*(it.second))(true);
55  return ret;
56 }
57 
58 /// Convert the value of a DenseI64ArrayAttr to a vector of unsigned indices.
60  SmallVector<unsigned> position;
61  llvm::append_range(position, indices);
62  return position;
63 }
64 
65 /// Convert an LLVM type to a string for printing in diagnostics.
66 static std::string diagStr(const llvm::Type *type) {
67  std::string str;
68  llvm::raw_string_ostream os(str);
69  type->print(os);
70  return str;
71 }
72 
73 /// Get the declaration of an overloaded llvm intrinsic. First we get the
74 /// overloaded argument types and/or result type from the CallIntrinsicOp, and
75 /// then use those to get the correct declaration of the overloaded intrinsic.
76 static FailureOr<llvm::Function *>
78  llvm::Module *module,
79  LLVM::ModuleTranslation &moduleTranslation) {
81  for (Type type : op->getOperandTypes())
82  allArgTys.push_back(moduleTranslation.convertType(type));
83 
84  llvm::Type *resTy;
85  if (op.getNumResults() == 0)
86  resTy = llvm::Type::getVoidTy(module->getContext());
87  else
88  resTy = moduleTranslation.convertType(op.getResult(0).getType());
89 
90  // ATM we do not support variadic intrinsics.
91  llvm::FunctionType *ft = llvm::FunctionType::get(resTy, allArgTys, false);
92 
94  getIntrinsicInfoTableEntries(id, table);
96 
97  SmallVector<llvm::Type *, 8> overloadedArgTys;
98  if (llvm::Intrinsic::matchIntrinsicSignature(ft, tableRef,
99  overloadedArgTys) !=
100  llvm::Intrinsic::MatchIntrinsicTypesResult::MatchIntrinsicTypes_Match) {
101  return mlir::emitError(op.getLoc(), "call intrinsic signature ")
102  << diagStr(ft) << " to overloaded intrinsic " << op.getIntrinAttr()
103  << " does not match any of the overloads";
104  }
105 
106  ArrayRef<llvm::Type *> overloadedArgTysRef = overloadedArgTys;
107  return llvm::Intrinsic::getOrInsertDeclaration(module, id,
108  overloadedArgTysRef);
109 }
110 
111 static llvm::OperandBundleDef
112 convertOperandBundle(OperandRange bundleOperands, StringRef bundleTag,
113  LLVM::ModuleTranslation &moduleTranslation) {
114  std::vector<llvm::Value *> operands;
115  operands.reserve(bundleOperands.size());
116  for (Value bundleArg : bundleOperands)
117  operands.push_back(moduleTranslation.lookupValue(bundleArg));
118  return llvm::OperandBundleDef(bundleTag.str(), std::move(operands));
119 }
120 
122 convertOperandBundles(OperandRangeRange bundleOperands, ArrayAttr bundleTags,
123  LLVM::ModuleTranslation &moduleTranslation) {
125  bundles.reserve(bundleOperands.size());
126 
127  for (auto [operands, tagAttr] : llvm::zip_equal(bundleOperands, bundleTags)) {
128  StringRef tag = cast<StringAttr>(tagAttr).getValue();
129  bundles.push_back(convertOperandBundle(operands, tag, moduleTranslation));
130  }
131  return bundles;
132 }
133 
136  std::optional<ArrayAttr> bundleTags,
137  LLVM::ModuleTranslation &moduleTranslation) {
138  if (!bundleTags)
139  return {};
140  return convertOperandBundles(bundleOperands, *bundleTags, moduleTranslation);
141 }
142 
143 /// Builder for LLVM_CallIntrinsicOp
144 static LogicalResult
145 convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder,
146  LLVM::ModuleTranslation &moduleTranslation) {
147  llvm::Module *module = builder.GetInsertBlock()->getModule();
149  llvm::Intrinsic::lookupIntrinsicID(op.getIntrinAttr());
150  if (!id)
151  return mlir::emitError(op.getLoc(), "could not find LLVM intrinsic: ")
152  << op.getIntrinAttr();
153 
154  llvm::Function *fn = nullptr;
155  if (llvm::Intrinsic::isOverloaded(id)) {
156  auto fnOrFailure =
157  getOverloadedDeclaration(op, id, module, moduleTranslation);
158  if (failed(fnOrFailure))
159  return failure();
160  fn = *fnOrFailure;
161  } else {
162  fn = llvm::Intrinsic::getOrInsertDeclaration(module, id, {});
163  }
164 
165  // Check the result type of the call.
166  const llvm::Type *intrinType =
167  op.getNumResults() == 0
168  ? llvm::Type::getVoidTy(module->getContext())
169  : moduleTranslation.convertType(op.getResultTypes().front());
170  if (intrinType != fn->getReturnType()) {
171  return mlir::emitError(op.getLoc(), "intrinsic call returns ")
172  << diagStr(intrinType) << " but " << op.getIntrinAttr()
173  << " actually returns " << diagStr(fn->getReturnType());
174  }
175 
176  // Check the argument types of the call. If the function is variadic, check
177  // the subrange of required arguments.
178  if (!fn->getFunctionType()->isVarArg() &&
179  op.getArgs().size() != fn->arg_size()) {
180  return mlir::emitError(op.getLoc(), "intrinsic call has ")
181  << op.getArgs().size() << " operands but " << op.getIntrinAttr()
182  << " expects " << fn->arg_size();
183  }
184  if (fn->getFunctionType()->isVarArg() &&
185  op.getArgs().size() < fn->arg_size()) {
186  return mlir::emitError(op.getLoc(), "intrinsic call has ")
187  << op.getArgs().size() << " operands but variadic "
188  << op.getIntrinAttr() << " expects at least " << fn->arg_size();
189  }
190  // Check the arguments up to the number the function requires.
191  for (unsigned i = 0, e = fn->arg_size(); i != e; ++i) {
192  const llvm::Type *expected = fn->getArg(i)->getType();
193  const llvm::Type *actual =
194  moduleTranslation.convertType(op.getOperandTypes()[i]);
195  if (actual != expected) {
196  return mlir::emitError(op.getLoc(), "intrinsic call operand #")
197  << i << " has type " << diagStr(actual) << " but "
198  << op.getIntrinAttr() << " expects " << diagStr(expected);
199  }
200  }
201 
202  FastmathFlagsInterface itf = op;
203  builder.setFastMathFlags(getFastmathFlags(itf));
204 
205  auto *inst = builder.CreateCall(
206  fn, moduleTranslation.lookupValues(op.getArgs()),
207  convertOperandBundles(op.getOpBundleOperands(), op.getOpBundleTags(),
208  moduleTranslation));
209 
210  if (failed(moduleTranslation.convertArgAndResultAttrs(op, inst)))
211  return failure();
212 
213  if (op.getNumResults() == 1)
214  moduleTranslation.mapValue(op->getResults().front()) = inst;
215  return success();
216 }
217 
218 static void convertLinkerOptionsOp(ArrayAttr options,
219  llvm::IRBuilderBase &builder,
220  LLVM::ModuleTranslation &moduleTranslation) {
221  llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
222  llvm::LLVMContext &context = llvmModule->getContext();
223  llvm::NamedMDNode *linkerMDNode =
224  llvmModule->getOrInsertNamedMetadata("llvm.linker.options");
226  MDNodes.reserve(options.size());
227  for (auto s : options.getAsRange<StringAttr>()) {
228  auto *MDNode = llvm::MDString::get(context, s.getValue());
229  MDNodes.push_back(MDNode);
230  }
231 
232  auto *listMDNode = llvm::MDTuple::get(context, MDNodes);
233  linkerMDNode->addOperand(listMDNode);
234 }
235 
236 static llvm::Metadata *
237 convertModuleFlagValue(StringRef key, ArrayAttr arrayAttr,
238  llvm::IRBuilderBase &builder,
239  LLVM::ModuleTranslation &moduleTranslation) {
240  llvm::LLVMContext &context = builder.getContext();
241  llvm::MDBuilder mdb(context);
243 
244  if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
245  for (auto entry : arrayAttr.getAsRange<ModuleFlagCGProfileEntryAttr>()) {
246  llvm::Metadata *fromMetadata =
247  entry.getFrom()
248  ? llvm::ValueAsMetadata::get(moduleTranslation.lookupFunction(
249  entry.getFrom().getValue()))
250  : nullptr;
251  llvm::Metadata *toMetadata =
252  entry.getTo()
254  moduleTranslation.lookupFunction(entry.getTo().getValue()))
255  : nullptr;
256 
257  llvm::Metadata *vals[] = {
258  fromMetadata, toMetadata,
259  mdb.createConstant(llvm::ConstantInt::get(
260  llvm::Type::getInt64Ty(context), entry.getCount()))};
261  nodes.push_back(llvm::MDNode::get(context, vals));
262  }
263  return llvm::MDTuple::getDistinct(context, nodes);
264  }
265  return nullptr;
266 }
267 
268 static llvm::Metadata *convertModuleFlagProfileSummaryAttr(
269  StringRef key, ModuleFlagProfileSummaryAttr summaryAttr,
270  llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) {
271  llvm::LLVMContext &context = builder.getContext();
272  llvm::MDBuilder mdb(context);
273 
274  auto getIntTuple = [&](StringRef key, uint64_t val) -> llvm::MDTuple * {
276  mdb.createString(key), mdb.createConstant(llvm::ConstantInt::get(
277  llvm::Type::getInt64Ty(context), val))};
278  return llvm::MDTuple::get(context, tupleNodes);
279  };
280 
282  mdb.createString("ProfileFormat"),
283  mdb.createString(
284  stringifyProfileSummaryFormatKind(summaryAttr.getFormat()))};
285 
287  llvm::MDTuple::get(context, fmtNode),
288  getIntTuple("TotalCount", summaryAttr.getTotalCount()),
289  getIntTuple("MaxCount", summaryAttr.getMaxCount()),
290  getIntTuple("MaxInternalCount", summaryAttr.getMaxInternalCount()),
291  getIntTuple("MaxFunctionCount", summaryAttr.getMaxFunctionCount()),
292  getIntTuple("NumCounts", summaryAttr.getNumCounts()),
293  getIntTuple("NumFunctions", summaryAttr.getNumFunctions()),
294  };
295 
296  if (summaryAttr.getIsPartialProfile())
297  vals.push_back(
298  getIntTuple("IsPartialProfile", *summaryAttr.getIsPartialProfile()));
299 
300  if (summaryAttr.getPartialProfileRatio()) {
302  mdb.createString("PartialProfileRatio"),
303  mdb.createConstant(llvm::ConstantFP::get(
304  llvm::Type::getDoubleTy(context),
305  summaryAttr.getPartialProfileRatio().getValue()))};
306  vals.push_back(llvm::MDTuple::get(context, tupleNodes));
307  }
308 
309  SmallVector<llvm::Metadata *> detailedEntries;
310  llvm::Type *llvmInt64Type = llvm::Type::getInt64Ty(context);
311  for (ModuleFlagProfileSummaryDetailedAttr detailedEntry :
312  summaryAttr.getDetailedSummary()) {
314  mdb.createConstant(
315  llvm::ConstantInt::get(llvmInt64Type, detailedEntry.getCutOff())),
316  mdb.createConstant(
317  llvm::ConstantInt::get(llvmInt64Type, detailedEntry.getMinCount())),
318  mdb.createConstant(llvm::ConstantInt::get(
319  llvmInt64Type, detailedEntry.getNumCounts()))};
320  detailedEntries.push_back(llvm::MDTuple::get(context, tupleNodes));
321  }
322  SmallVector<llvm::Metadata *> detailedSummary{
323  mdb.createString("DetailedSummary"),
324  llvm::MDTuple::get(context, detailedEntries)};
325  vals.push_back(llvm::MDTuple::get(context, detailedSummary));
326 
327  return llvm::MDNode::get(context, vals);
328 }
329 
330 static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
331  LLVM::ModuleTranslation &moduleTranslation) {
332  llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
333  for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>()) {
334  llvm::Metadata *valueMetadata =
336  .Case<StringAttr>([&](auto strAttr) {
337  return llvm::MDString::get(builder.getContext(),
338  strAttr.getValue());
339  })
340  .Case<IntegerAttr>([&](auto intAttr) {
342  llvm::Type::getInt32Ty(builder.getContext()),
343  intAttr.getInt()));
344  })
345  .Case<ArrayAttr>([&](auto arrayAttr) {
346  return convertModuleFlagValue(flagAttr.getKey().getValue(),
347  arrayAttr, builder,
348  moduleTranslation);
349  })
350  .Case([&](ModuleFlagProfileSummaryAttr summaryAttr) {
352  flagAttr.getKey().getValue(), summaryAttr, builder,
353  moduleTranslation);
354  })
355  .Default([](auto) { return nullptr; });
356 
357  assert(valueMetadata && "expected valid metadata");
358  llvmModule->addModuleFlag(
359  convertModFlagBehaviorToLLVM(flagAttr.getBehavior()),
360  flagAttr.getKey().getValue(), valueMetadata);
361  }
362 }
363 
364 static llvm::DILocalScope *
365 getLocalScopeFromLoc(llvm::IRBuilderBase &builder, Location loc,
366  LLVM::ModuleTranslation &moduleTranslation) {
367  if (auto scopeLoc =
369  if (auto *localScope = llvm::dyn_cast<llvm::DILocalScope>(
370  moduleTranslation.translateDebugInfo(scopeLoc.getMetadata())))
371  return localScope;
372  return builder.GetInsertBlock()->getParent()->getSubprogram();
373 }
374 
375 static LogicalResult
376 convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
377  LLVM::ModuleTranslation &moduleTranslation) {
378 
379  llvm::IRBuilder<>::FastMathFlagGuard fmfGuard(builder);
380  if (auto fmf = dyn_cast<FastmathFlagsInterface>(opInst))
381  builder.setFastMathFlags(getFastmathFlags(fmf));
382 
383 #include "mlir/Dialect/LLVMIR/LLVMConversions.inc"
384 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicConversions.inc"
385 
386  // Emit function calls. If the "callee" attribute is present, this is a
387  // direct function call and we also need to look up the remapped function
388  // itself. Otherwise, this is an indirect call and the callee is the first
389  // operand, look it up as a normal value.
390  if (auto callOp = dyn_cast<LLVM::CallOp>(opInst)) {
391  auto operands = moduleTranslation.lookupValues(callOp.getCalleeOperands());
393  convertOperandBundles(callOp.getOpBundleOperands(),
394  callOp.getOpBundleTags(), moduleTranslation);
395  ArrayRef<llvm::Value *> operandsRef(operands);
396  llvm::CallInst *call;
397  if (auto attr = callOp.getCalleeAttr()) {
398  if (llvm::Function *function =
399  moduleTranslation.lookupFunction(attr.getValue())) {
400  call = builder.CreateCall(function, operandsRef, opBundles);
401  } else {
402  Operation *moduleOp = parentLLVMModule(&opInst);
403  Operation *ifuncOp =
404  moduleTranslation.symbolTable().lookupSymbolIn(moduleOp, attr);
405  llvm::GlobalValue *ifunc = moduleTranslation.lookupIFunc(ifuncOp);
406  llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
407  moduleTranslation.convertType(callOp.getCalleeFunctionType()));
408  call = builder.CreateCall(calleeType, ifunc, operandsRef, opBundles);
409  }
410  } else {
411  llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
412  moduleTranslation.convertType(callOp.getCalleeFunctionType()));
413  call = builder.CreateCall(calleeType, operandsRef.front(),
414  operandsRef.drop_front(), opBundles);
415  }
416  call->setCallingConv(convertCConvToLLVM(callOp.getCConv()));
417  call->setTailCallKind(convertTailCallKindToLLVM(callOp.getTailCallKind()));
418  if (callOp.getConvergentAttr())
419  call->addFnAttr(llvm::Attribute::Convergent);
420  if (callOp.getNoUnwindAttr())
421  call->addFnAttr(llvm::Attribute::NoUnwind);
422  if (callOp.getWillReturnAttr())
423  call->addFnAttr(llvm::Attribute::WillReturn);
424  if (callOp.getNoInlineAttr())
425  call->addFnAttr(llvm::Attribute::NoInline);
426  if (callOp.getAlwaysInlineAttr())
427  call->addFnAttr(llvm::Attribute::AlwaysInline);
428  if (callOp.getInlineHintAttr())
429  call->addFnAttr(llvm::Attribute::InlineHint);
430 
431  if (failed(moduleTranslation.convertArgAndResultAttrs(callOp, call)))
432  return failure();
433 
434  if (MemoryEffectsAttr memAttr = callOp.getMemoryEffectsAttr()) {
435  llvm::MemoryEffects memEffects =
436  llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
437  convertModRefInfoToLLVM(memAttr.getArgMem())) |
438  llvm::MemoryEffects(
439  llvm::MemoryEffects::Location::InaccessibleMem,
440  convertModRefInfoToLLVM(memAttr.getInaccessibleMem())) |
441  llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
442  convertModRefInfoToLLVM(memAttr.getOther()));
443  call->setMemoryEffects(memEffects);
444  }
445 
446  moduleTranslation.setAccessGroupsMetadata(callOp, call);
447  moduleTranslation.setAliasScopeMetadata(callOp, call);
448  moduleTranslation.setTBAAMetadata(callOp, call);
449  // If the called function has a result, remap the corresponding value. Note
450  // that LLVM IR dialect CallOp has either 0 or 1 result.
451  if (opInst.getNumResults() != 0)
452  moduleTranslation.mapValue(opInst.getResult(0), call);
453  // Check that LLVM call returns void for 0-result functions.
454  else if (!call->getType()->isVoidTy())
455  return failure();
456  moduleTranslation.mapCall(callOp, call);
457  return success();
458  }
459 
460  if (auto inlineAsmOp = dyn_cast<LLVM::InlineAsmOp>(opInst)) {
461  // TODO: refactor function type creation which usually occurs in std-LLVM
462  // conversion.
463  SmallVector<Type, 8> operandTypes;
464  llvm::append_range(operandTypes, inlineAsmOp.getOperands().getTypes());
465 
466  Type resultType;
467  if (inlineAsmOp.getNumResults() == 0) {
468  resultType = LLVM::LLVMVoidType::get(&moduleTranslation.getContext());
469  } else {
470  assert(inlineAsmOp.getNumResults() == 1);
471  resultType = inlineAsmOp.getResultTypes()[0];
472  }
473  auto ft = LLVM::LLVMFunctionType::get(resultType, operandTypes);
474  llvm::InlineAsm *inlineAsmInst =
475  inlineAsmOp.getAsmDialect()
477  static_cast<llvm::FunctionType *>(
478  moduleTranslation.convertType(ft)),
479  inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
480  inlineAsmOp.getHasSideEffects(),
481  inlineAsmOp.getIsAlignStack(),
482  convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
483  : llvm::InlineAsm::get(static_cast<llvm::FunctionType *>(
484  moduleTranslation.convertType(ft)),
485  inlineAsmOp.getAsmString(),
486  inlineAsmOp.getConstraints(),
487  inlineAsmOp.getHasSideEffects(),
488  inlineAsmOp.getIsAlignStack());
489  llvm::CallInst *inst = builder.CreateCall(
490  inlineAsmInst,
491  moduleTranslation.lookupValues(inlineAsmOp.getOperands()));
492  inst->setTailCallKind(convertTailCallKindToLLVM(
493  inlineAsmOp.getTailCallKindAttr().getTailCallKind()));
494  if (auto maybeOperandAttrs = inlineAsmOp.getOperandAttrs()) {
495  llvm::AttributeList attrList;
496  for (const auto &it : llvm::enumerate(*maybeOperandAttrs)) {
497  Attribute attr = it.value();
498  if (!attr)
499  continue;
500  DictionaryAttr dAttr = cast<DictionaryAttr>(attr);
501  if (dAttr.empty())
502  continue;
503  TypeAttr tAttr =
504  cast<TypeAttr>(dAttr.get(InlineAsmOp::getElementTypeAttrName()));
505  llvm::AttrBuilder b(moduleTranslation.getLLVMContext());
506  llvm::Type *ty = moduleTranslation.convertType(tAttr.getValue());
507  b.addTypeAttr(llvm::Attribute::ElementType, ty);
508  // shift to account for the returned value (this is always 1 aggregate
509  // value in LLVM).
510  int shift = (opInst.getNumResults() > 0) ? 1 : 0;
511  attrList = attrList.addAttributesAtIndex(
512  moduleTranslation.getLLVMContext(), it.index() + shift, b);
513  }
514  inst->setAttributes(attrList);
515  }
516 
517  if (opInst.getNumResults() != 0)
518  moduleTranslation.mapValue(opInst.getResult(0), inst);
519  return success();
520  }
521 
522  if (auto invOp = dyn_cast<LLVM::InvokeOp>(opInst)) {
523  auto operands = moduleTranslation.lookupValues(invOp.getCalleeOperands());
525  convertOperandBundles(invOp.getOpBundleOperands(),
526  invOp.getOpBundleTags(), moduleTranslation);
527  ArrayRef<llvm::Value *> operandsRef(operands);
528  llvm::InvokeInst *result;
529  if (auto attr = opInst.getAttrOfType<FlatSymbolRefAttr>("callee")) {
530  result = builder.CreateInvoke(
531  moduleTranslation.lookupFunction(attr.getValue()),
532  moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
533  moduleTranslation.lookupBlock(invOp.getSuccessor(1)), operandsRef,
534  opBundles);
535  } else {
536  llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
537  moduleTranslation.convertType(invOp.getCalleeFunctionType()));
538  result = builder.CreateInvoke(
539  calleeType, operandsRef.front(),
540  moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
541  moduleTranslation.lookupBlock(invOp.getSuccessor(1)),
542  operandsRef.drop_front(), opBundles);
543  }
544  result->setCallingConv(convertCConvToLLVM(invOp.getCConv()));
545  if (failed(moduleTranslation.convertArgAndResultAttrs(invOp, result)))
546  return failure();
547  moduleTranslation.mapBranch(invOp, result);
548  // InvokeOp can only have 0 or 1 result
549  if (invOp->getNumResults() != 0) {
550  moduleTranslation.mapValue(opInst.getResult(0), result);
551  return success();
552  }
553  return success(result->getType()->isVoidTy());
554  }
555 
556  if (auto lpOp = dyn_cast<LLVM::LandingpadOp>(opInst)) {
557  llvm::Type *ty = moduleTranslation.convertType(lpOp.getType());
558  llvm::LandingPadInst *lpi =
559  builder.CreateLandingPad(ty, lpOp.getNumOperands());
560  lpi->setCleanup(lpOp.getCleanup());
561 
562  // Add clauses
563  for (llvm::Value *operand :
564  moduleTranslation.lookupValues(lpOp.getOperands())) {
565  // All operands should be constant - checked by verifier
566  if (auto *constOperand = dyn_cast<llvm::Constant>(operand))
567  lpi->addClause(constOperand);
568  }
569  moduleTranslation.mapValue(lpOp.getResult(), lpi);
570  return success();
571  }
572 
573  // Emit branches. We need to look up the remapped blocks and ignore the
574  // block arguments that were transformed into PHI nodes.
575  if (auto brOp = dyn_cast<LLVM::BrOp>(opInst)) {
576  llvm::BranchInst *branch =
577  builder.CreateBr(moduleTranslation.lookupBlock(brOp.getSuccessor()));
578  moduleTranslation.mapBranch(&opInst, branch);
579  moduleTranslation.setLoopMetadata(&opInst, branch);
580  return success();
581  }
582  if (auto condbrOp = dyn_cast<LLVM::CondBrOp>(opInst)) {
583  llvm::BranchInst *branch = builder.CreateCondBr(
584  moduleTranslation.lookupValue(condbrOp.getOperand(0)),
585  moduleTranslation.lookupBlock(condbrOp.getSuccessor(0)),
586  moduleTranslation.lookupBlock(condbrOp.getSuccessor(1)));
587  moduleTranslation.mapBranch(&opInst, branch);
588  moduleTranslation.setLoopMetadata(&opInst, branch);
589  return success();
590  }
591  if (auto switchOp = dyn_cast<LLVM::SwitchOp>(opInst)) {
592  llvm::SwitchInst *switchInst = builder.CreateSwitch(
593  moduleTranslation.lookupValue(switchOp.getValue()),
594  moduleTranslation.lookupBlock(switchOp.getDefaultDestination()),
595  switchOp.getCaseDestinations().size());
596 
597  // Handle switch with zero cases.
598  if (!switchOp.getCaseValues())
599  return success();
600 
601  auto *ty = llvm::cast<llvm::IntegerType>(
602  moduleTranslation.convertType(switchOp.getValue().getType()));
603  for (auto i :
604  llvm::zip(llvm::cast<DenseIntElementsAttr>(*switchOp.getCaseValues()),
605  switchOp.getCaseDestinations()))
606  switchInst->addCase(
607  llvm::ConstantInt::get(ty, std::get<0>(i).getLimitedValue()),
608  moduleTranslation.lookupBlock(std::get<1>(i)));
609 
610  moduleTranslation.mapBranch(&opInst, switchInst);
611  return success();
612  }
613  if (auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(opInst)) {
614  llvm::IndirectBrInst *indBr = builder.CreateIndirectBr(
615  moduleTranslation.lookupValue(indBrOp.getAddr()),
616  indBrOp->getNumSuccessors());
617  for (auto *succ : indBrOp.getSuccessors())
618  indBr->addDestination(moduleTranslation.lookupBlock(succ));
619  moduleTranslation.mapBranch(&opInst, indBr);
620  return success();
621  }
622 
623  // Emit addressof. We need to look up the global value referenced by the
624  // operation and store it in the MLIR-to-LLVM value mapping. This does not
625  // emit any LLVM instruction.
626  if (auto addressOfOp = dyn_cast<LLVM::AddressOfOp>(opInst)) {
627  LLVM::GlobalOp global =
628  addressOfOp.getGlobal(moduleTranslation.symbolTable());
629  LLVM::LLVMFuncOp function =
630  addressOfOp.getFunction(moduleTranslation.symbolTable());
631  LLVM::AliasOp alias = addressOfOp.getAlias(moduleTranslation.symbolTable());
632  LLVM::IFuncOp ifunc = addressOfOp.getIFunc(moduleTranslation.symbolTable());
633 
634  // The verifier should not have allowed this.
635  assert((global || function || alias || ifunc) &&
636  "referencing an undefined global, function, alias, or ifunc");
637 
638  llvm::Value *llvmValue = nullptr;
639  if (global)
640  llvmValue = moduleTranslation.lookupGlobal(global);
641  else if (alias)
642  llvmValue = moduleTranslation.lookupAlias(alias);
643  else if (function)
644  llvmValue = moduleTranslation.lookupFunction(function.getName());
645  else
646  llvmValue = moduleTranslation.lookupIFunc(ifunc);
647 
648  moduleTranslation.mapValue(addressOfOp.getResult(), llvmValue);
649  return success();
650  }
651 
652  // Emit dso_local_equivalent. We need to look up the global value referenced
653  // by the operation and store it in the MLIR-to-LLVM value mapping.
654  if (auto dsoLocalEquivalentOp =
655  dyn_cast<LLVM::DSOLocalEquivalentOp>(opInst)) {
656  LLVM::LLVMFuncOp function =
657  dsoLocalEquivalentOp.getFunction(moduleTranslation.symbolTable());
658  LLVM::AliasOp alias =
659  dsoLocalEquivalentOp.getAlias(moduleTranslation.symbolTable());
660 
661  // The verifier should not have allowed this.
662  assert((function || alias) &&
663  "referencing an undefined function, or alias");
664 
665  llvm::Value *llvmValue = nullptr;
666  if (alias)
667  llvmValue = moduleTranslation.lookupAlias(alias);
668  else
669  llvmValue = moduleTranslation.lookupFunction(function.getName());
670 
671  moduleTranslation.mapValue(
672  dsoLocalEquivalentOp.getResult(),
673  llvm::DSOLocalEquivalent::get(cast<llvm::GlobalValue>(llvmValue)));
674  return success();
675  }
676 
677  // Emit blockaddress. We first need to find the LLVM block referenced by this
678  // operation and then create a LLVM block address for it.
679  if (auto blockAddressOp = dyn_cast<LLVM::BlockAddressOp>(opInst)) {
680  BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
681  llvm::BasicBlock *llvmBlock =
682  moduleTranslation.lookupBlockAddress(blockAddressAttr);
683 
684  llvm::Value *llvmValue = nullptr;
685  StringRef fnName = blockAddressAttr.getFunction().getValue();
686  if (llvmBlock) {
687  llvm::Function *llvmFn = moduleTranslation.lookupFunction(fnName);
688  llvmValue = llvm::BlockAddress::get(llvmFn, llvmBlock);
689  } else {
690  // The matching LLVM block is not yet emitted, a placeholder is created
691  // in its place. When the LLVM block is emitted later in translation,
692  // the llvmValue is replaced with the actual llvm::BlockAddress.
693  // A GlobalVariable is chosen as placeholder because in general LLVM
694  // constants are uniqued and are not proper for RAUW, since that could
695  // harm unrelated uses of the constant.
696  llvmValue = new llvm::GlobalVariable(
697  *moduleTranslation.getLLVMModule(),
698  llvm::PointerType::getUnqual(moduleTranslation.getLLVMContext()),
699  /*isConstant=*/true, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
700  /*Initializer=*/nullptr,
701  Twine("__mlir_block_address_")
702  .concat(Twine(fnName))
703  .concat(Twine((uint64_t)blockAddressOp.getOperation())));
704  moduleTranslation.mapUnresolvedBlockAddress(blockAddressOp, llvmValue);
705  }
706 
707  moduleTranslation.mapValue(blockAddressOp.getResult(), llvmValue);
708  return success();
709  }
710 
711  // Emit block label. If this label is seen before BlockAddressOp is
712  // translated, go ahead and already map it.
713  if (auto blockTagOp = dyn_cast<LLVM::BlockTagOp>(opInst)) {
714  auto funcOp = blockTagOp->getParentOfType<LLVMFuncOp>();
715  BlockAddressAttr blockAddressAttr = BlockAddressAttr::get(
716  &moduleTranslation.getContext(),
717  FlatSymbolRefAttr::get(&moduleTranslation.getContext(),
718  funcOp.getName()),
719  blockTagOp.getTag());
720  moduleTranslation.mapBlockAddress(blockAddressAttr,
721  builder.GetInsertBlock());
722  return success();
723  }
724 
725  return failure();
726 }
727 
728 static LogicalResult
730  NamedAttribute attribute,
731  LLVM::ModuleTranslation &moduleTranslation) {
732  StringRef name = attribute.getName();
733  if (name == LLVMDialect::getMmraAttrName()) {
735  if (auto oneTag = dyn_cast<LLVM::MMRATagAttr>(attribute.getValue())) {
736  tags.emplace_back(oneTag.getPrefix(), oneTag.getSuffix());
737  } else if (auto manyTags = dyn_cast<ArrayAttr>(attribute.getValue())) {
738  for (Attribute attr : manyTags) {
739  auto tag = dyn_cast<MMRATagAttr>(attr);
740  if (!tag)
741  return op.emitOpError(
742  "MMRA annotations array contains value that isn't an MMRA tag");
743  tags.emplace_back(tag.getPrefix(), tag.getSuffix());
744  }
745  } else {
746  return op.emitOpError(
747  "llvm.mmra is something other than an MMRA tag or an array of them");
748  }
749  llvm::MDTuple *mmraMd =
750  llvm::MMRAMetadata::getMD(moduleTranslation.getLLVMContext(), tags);
751  if (!mmraMd) {
752  // Empty list, canonicalizes to nothing
753  return success();
754  }
755  for (llvm::Instruction *inst : instructions)
756  inst->setMetadata(llvm::LLVMContext::MD_mmra, mmraMd);
757  return success();
758  }
759  return success();
760 }
761 
762 namespace {
763 /// Implementation of the dialect interface that converts operations belonging
764 /// to the LLVM dialect to LLVM IR.
765 class LLVMDialectLLVMIRTranslationInterface
767 public:
769 
770  /// Translates the given operation to LLVM IR using the provided IR builder
771  /// and saving the state in `moduleTranslation`.
772  LogicalResult
773  convertOperation(Operation *op, llvm::IRBuilderBase &builder,
774  LLVM::ModuleTranslation &moduleTranslation) const final {
775  return convertOperationImpl(*op, builder, moduleTranslation);
776  }
777 
778  /// Handle some metadata that is represented as a discardable attribute.
779  LogicalResult
780  amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
781  NamedAttribute attribute,
782  LLVM::ModuleTranslation &moduleTranslation) const final {
783  return amendOperationImpl(*op, instructions, attribute, moduleTranslation);
784  }
785 };
786 } // namespace
787 
789  registry.insert<LLVM::LLVMDialect>();
790  registry.addExtension(+[](MLIRContext *ctx, LLVM::LLVMDialect *dialect) {
791  dialect->addInterfaces<LLVMDialectLLVMIRTranslationInterface>();
792  });
793 }
794 
796  DialectRegistry registry;
798  context.appendDialectRegistry(registry);
799 }
static SmallVector< unsigned > extractPosition(ArrayRef< int64_t > indices)
Convert the value of a DenseI64ArrayAttr to a vector of unsigned indices.
static std::string diagStr(const llvm::Type *type)
Convert an LLVM type to a string for printing in diagnostics.
static llvm::Metadata * convertModuleFlagProfileSummaryAttr(StringRef key, ModuleFlagProfileSummaryAttr summaryAttr, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::DILocalScope * getLocalScopeFromLoc(llvm::IRBuilderBase &builder, Location loc, LLVM::ModuleTranslation &moduleTranslation)
static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static FailureOr< llvm::Function * > getOverloadedDeclaration(CallIntrinsicOp op, llvm::Intrinsic::ID id, llvm::Module *module, LLVM::ModuleTranslation &moduleTranslation)
Get the declaration of an overloaded llvm intrinsic.
static LogicalResult convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static SmallVector< llvm::OperandBundleDef > convertOperandBundles(OperandRangeRange bundleOperands, ArrayAttr bundleTags, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Builder for LLVM_CallIntrinsicOp.
static LogicalResult amendOperationImpl(Operation &op, ArrayRef< llvm::Instruction * > instructions, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation)
static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op)
static llvm::OperandBundleDef convertOperandBundle(OperandRange bundleOperands, StringRef bundleTag, LLVM::ModuleTranslation &moduleTranslation)
static llvm::Metadata * convertModuleFlagValue(StringRef key, ArrayAttr arrayAttr, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void convertLinkerOptionsOp(ArrayAttr options, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::ManagedStatic< PassManagerOptions > options
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.
const float * table
Attributes are known-constant values of operations.
Definition: Attributes.h:25
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
A symbol reference with a reference path containing a single element.
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
This class represents a fused location whose metadata is known to be an instance of the given type.
Definition: Location.h:149
Base class for dialect interfaces providing translation to LLVM IR.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
Definition: Location.h:45
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:63
void appendDialectRegistry(const DialectRegistry &registry)
Append the contents of the given dialect registry to the registry associated with this context.
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:164
StringAttr getName() const
Return the name of the attribute.
Definition: Attributes.cpp:55
Attribute getValue() const
Return the value of the attribute.
Definition: Attributes.h:179
This class represents a contiguous range of operand ranges, e.g.
Definition: ValueRange.h:84
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:43
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
AttrClass getAttrOfType(StringAttr name)
Definition: Operation.h:550
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition: Operation.h:407
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Definition: Operation.cpp:672
unsigned getNumResults()
Return the number of results held by this operation.
Definition: Operation.h:404
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
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.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:344
SmallVector< AffineExpr, 4 > concat(ArrayRef< AffineExpr > a, ArrayRef< AffineExpr > b)
Return the vector that is the concatenation of a and b.
Definition: LinalgOps.cpp:2465
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition: Remarks.h:491
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
void registerLLVMDialectTranslation(DialectRegistry &registry)
Register the LLVM dialect and the translation from it to the LLVM IR in the given registry;.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...