MLIR  21.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/ADT/TypeSwitch.h"
20 #include "llvm/IR/IRBuilder.h"
21 #include "llvm/IR/InlineAsm.h"
22 #include "llvm/IR/MDBuilder.h"
23 #include "llvm/IR/MatrixBuilder.h"
24 #include "llvm/IR/Operator.h"
25 
26 using namespace mlir;
27 using namespace mlir::LLVM;
29 
30 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
31 
32 static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op) {
33  using llvmFMF = llvm::FastMathFlags;
34  using FuncT = void (llvmFMF::*)(bool);
35  const std::pair<FastmathFlags, FuncT> handlers[] = {
36  // clang-format off
37  {FastmathFlags::nnan, &llvmFMF::setNoNaNs},
38  {FastmathFlags::ninf, &llvmFMF::setNoInfs},
39  {FastmathFlags::nsz, &llvmFMF::setNoSignedZeros},
40  {FastmathFlags::arcp, &llvmFMF::setAllowReciprocal},
41  {FastmathFlags::contract, &llvmFMF::setAllowContract},
42  {FastmathFlags::afn, &llvmFMF::setApproxFunc},
43  {FastmathFlags::reassoc, &llvmFMF::setAllowReassoc},
44  // clang-format on
45  };
46  llvm::FastMathFlags ret;
47  ::mlir::LLVM::FastmathFlags fmfMlir = op.getFastmathAttr().getValue();
48  for (auto it : handlers)
49  if (bitEnumContainsAll(fmfMlir, it.first))
50  (ret.*(it.second))(true);
51  return ret;
52 }
53 
54 /// Convert the value of a DenseI64ArrayAttr to a vector of unsigned indices.
56  SmallVector<unsigned> position;
57  llvm::append_range(position, indices);
58  return position;
59 }
60 
61 /// Convert an LLVM type to a string for printing in diagnostics.
62 static std::string diagStr(const llvm::Type *type) {
63  std::string str;
64  llvm::raw_string_ostream os(str);
65  type->print(os);
66  return str;
67 }
68 
69 /// Get the declaration of an overloaded llvm intrinsic. First we get the
70 /// overloaded argument types and/or result type from the CallIntrinsicOp, and
71 /// then use those to get the correct declaration of the overloaded intrinsic.
72 static FailureOr<llvm::Function *>
74  llvm::Module *module,
75  LLVM::ModuleTranslation &moduleTranslation) {
77  for (Type type : op->getOperandTypes())
78  allArgTys.push_back(moduleTranslation.convertType(type));
79 
80  llvm::Type *resTy;
81  if (op.getNumResults() == 0)
82  resTy = llvm::Type::getVoidTy(module->getContext());
83  else
84  resTy = moduleTranslation.convertType(op.getResult(0).getType());
85 
86  // ATM we do not support variadic intrinsics.
87  llvm::FunctionType *ft = llvm::FunctionType::get(resTy, allArgTys, false);
88 
90  getIntrinsicInfoTableEntries(id, table);
92 
93  SmallVector<llvm::Type *, 8> overloadedArgTys;
94  if (llvm::Intrinsic::matchIntrinsicSignature(ft, tableRef,
95  overloadedArgTys) !=
96  llvm::Intrinsic::MatchIntrinsicTypesResult::MatchIntrinsicTypes_Match) {
97  return mlir::emitError(op.getLoc(), "call intrinsic signature ")
98  << diagStr(ft) << " to overloaded intrinsic " << op.getIntrinAttr()
99  << " does not match any of the overloads";
100  }
101 
102  ArrayRef<llvm::Type *> overloadedArgTysRef = overloadedArgTys;
103  return llvm::Intrinsic::getOrInsertDeclaration(module, id,
104  overloadedArgTysRef);
105 }
106 
107 static llvm::OperandBundleDef
108 convertOperandBundle(OperandRange bundleOperands, StringRef bundleTag,
109  LLVM::ModuleTranslation &moduleTranslation) {
110  std::vector<llvm::Value *> operands;
111  operands.reserve(bundleOperands.size());
112  for (Value bundleArg : bundleOperands)
113  operands.push_back(moduleTranslation.lookupValue(bundleArg));
114  return llvm::OperandBundleDef(bundleTag.str(), std::move(operands));
115 }
116 
118 convertOperandBundles(OperandRangeRange bundleOperands, ArrayAttr bundleTags,
119  LLVM::ModuleTranslation &moduleTranslation) {
121  bundles.reserve(bundleOperands.size());
122 
123  for (auto [operands, tagAttr] : llvm::zip_equal(bundleOperands, bundleTags)) {
124  StringRef tag = cast<StringAttr>(tagAttr).getValue();
125  bundles.push_back(convertOperandBundle(operands, tag, moduleTranslation));
126  }
127  return bundles;
128 }
129 
132  std::optional<ArrayAttr> bundleTags,
133  LLVM::ModuleTranslation &moduleTranslation) {
134  if (!bundleTags)
135  return {};
136  return convertOperandBundles(bundleOperands, *bundleTags, moduleTranslation);
137 }
138 
139 static LogicalResult
140 convertParameterAndResultAttrs(mlir::Location loc, ArrayAttr argAttrsArray,
141  ArrayAttr resAttrsArray, llvm::CallBase *call,
142  LLVM::ModuleTranslation &moduleTranslation) {
143  if (argAttrsArray) {
144  for (auto [argIdx, argAttrsAttr] : llvm::enumerate(argAttrsArray)) {
145  if (auto argAttrs = cast<DictionaryAttr>(argAttrsAttr);
146  !argAttrs.empty()) {
147  FailureOr<llvm::AttrBuilder> attrBuilder =
148  moduleTranslation.convertParameterAttrs(loc, argAttrs);
149  if (failed(attrBuilder))
150  return failure();
151  call->addParamAttrs(argIdx, *attrBuilder);
152  }
153  }
154  }
155 
156  if (resAttrsArray && resAttrsArray.size() > 0) {
157  if (resAttrsArray.size() != 1)
158  return mlir::emitError(loc, "llvm.func cannot have multiple results");
159  if (auto resAttrs = cast<DictionaryAttr>(resAttrsArray[0]);
160  !resAttrs.empty()) {
161  FailureOr<llvm::AttrBuilder> attrBuilder =
162  moduleTranslation.convertParameterAttrs(loc, resAttrs);
163  if (failed(attrBuilder))
164  return failure();
165  call->addRetAttrs(*attrBuilder);
166  }
167  }
168  return success();
169 }
170 
171 static LogicalResult
172 convertParameterAndResultAttrs(CallOpInterface callOp, llvm::CallBase *call,
173  LLVM::ModuleTranslation &moduleTranslation) {
175  callOp.getLoc(), callOp.getArgAttrsAttr(), callOp.getResAttrsAttr(), call,
176  moduleTranslation);
177 }
178 
179 /// Builder for LLVM_CallIntrinsicOp
180 static LogicalResult
181 convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder,
182  LLVM::ModuleTranslation &moduleTranslation) {
183  llvm::Module *module = builder.GetInsertBlock()->getModule();
185  llvm::Intrinsic::lookupIntrinsicID(op.getIntrinAttr());
186  if (!id)
187  return mlir::emitError(op.getLoc(), "could not find LLVM intrinsic: ")
188  << op.getIntrinAttr();
189 
190  llvm::Function *fn = nullptr;
191  if (llvm::Intrinsic::isOverloaded(id)) {
192  auto fnOrFailure =
193  getOverloadedDeclaration(op, id, module, moduleTranslation);
194  if (failed(fnOrFailure))
195  return failure();
196  fn = *fnOrFailure;
197  } else {
198  fn = llvm::Intrinsic::getOrInsertDeclaration(module, id, {});
199  }
200 
201  // Check the result type of the call.
202  const llvm::Type *intrinType =
203  op.getNumResults() == 0
204  ? llvm::Type::getVoidTy(module->getContext())
205  : moduleTranslation.convertType(op.getResultTypes().front());
206  if (intrinType != fn->getReturnType()) {
207  return mlir::emitError(op.getLoc(), "intrinsic call returns ")
208  << diagStr(intrinType) << " but " << op.getIntrinAttr()
209  << " actually returns " << diagStr(fn->getReturnType());
210  }
211 
212  // Check the argument types of the call. If the function is variadic, check
213  // the subrange of required arguments.
214  if (!fn->getFunctionType()->isVarArg() &&
215  op.getArgs().size() != fn->arg_size()) {
216  return mlir::emitError(op.getLoc(), "intrinsic call has ")
217  << op.getArgs().size() << " operands but " << op.getIntrinAttr()
218  << " expects " << fn->arg_size();
219  }
220  if (fn->getFunctionType()->isVarArg() &&
221  op.getArgs().size() < fn->arg_size()) {
222  return mlir::emitError(op.getLoc(), "intrinsic call has ")
223  << op.getArgs().size() << " operands but variadic "
224  << op.getIntrinAttr() << " expects at least " << fn->arg_size();
225  }
226  // Check the arguments up to the number the function requires.
227  for (unsigned i = 0, e = fn->arg_size(); i != e; ++i) {
228  const llvm::Type *expected = fn->getArg(i)->getType();
229  const llvm::Type *actual =
230  moduleTranslation.convertType(op.getOperandTypes()[i]);
231  if (actual != expected) {
232  return mlir::emitError(op.getLoc(), "intrinsic call operand #")
233  << i << " has type " << diagStr(actual) << " but "
234  << op.getIntrinAttr() << " expects " << diagStr(expected);
235  }
236  }
237 
238  FastmathFlagsInterface itf = op;
239  builder.setFastMathFlags(getFastmathFlags(itf));
240 
241  auto *inst = builder.CreateCall(
242  fn, moduleTranslation.lookupValues(op.getArgs()),
243  convertOperandBundles(op.getOpBundleOperands(), op.getOpBundleTags(),
244  moduleTranslation));
245 
246  if (failed(convertParameterAndResultAttrs(op.getLoc(), op.getArgAttrsAttr(),
247  op.getResAttrsAttr(), inst,
248  moduleTranslation)))
249  return failure();
250 
251  if (op.getNumResults() == 1)
252  moduleTranslation.mapValue(op->getResults().front()) = inst;
253  return success();
254 }
255 
256 static void convertLinkerOptionsOp(ArrayAttr options,
257  llvm::IRBuilderBase &builder,
258  LLVM::ModuleTranslation &moduleTranslation) {
259  llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
260  llvm::LLVMContext &context = llvmModule->getContext();
261  llvm::NamedMDNode *linkerMDNode =
262  llvmModule->getOrInsertNamedMetadata("llvm.linker.options");
264  MDNodes.reserve(options.size());
265  for (auto s : options.getAsRange<StringAttr>()) {
266  auto *MDNode = llvm::MDString::get(context, s.getValue());
267  MDNodes.push_back(MDNode);
268  }
269 
270  auto *listMDNode = llvm::MDTuple::get(context, MDNodes);
271  linkerMDNode->addOperand(listMDNode);
272 }
273 
274 static llvm::Metadata *
275 convertModuleFlagValue(StringRef key, ArrayAttr arrayAttr,
276  llvm::IRBuilderBase &builder,
277  LLVM::ModuleTranslation &moduleTranslation) {
278  llvm::LLVMContext &context = builder.getContext();
279  llvm::MDBuilder mdb(context);
281 
282  if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
283  for (auto entry : arrayAttr.getAsRange<ModuleFlagCGProfileEntryAttr>()) {
284  llvm::Metadata *fromMetadata =
285  entry.getFrom()
286  ? llvm::ValueAsMetadata::get(moduleTranslation.lookupFunction(
287  entry.getFrom().getValue()))
288  : nullptr;
289  llvm::Metadata *toMetadata =
290  entry.getTo()
292  moduleTranslation.lookupFunction(entry.getTo().getValue()))
293  : nullptr;
294 
295  llvm::Metadata *vals[] = {
296  fromMetadata, toMetadata,
297  mdb.createConstant(llvm::ConstantInt::get(
298  llvm::Type::getInt64Ty(context), entry.getCount()))};
299  nodes.push_back(llvm::MDNode::get(context, vals));
300  }
301  return llvm::MDTuple::getDistinct(context, nodes);
302  }
303  return nullptr;
304 }
305 
306 static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
307  LLVM::ModuleTranslation &moduleTranslation) {
308  llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
309  for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>()) {
310  llvm::Metadata *valueMetadata =
312  .Case<StringAttr>([&](auto strAttr) {
313  return llvm::MDString::get(builder.getContext(),
314  strAttr.getValue());
315  })
316  .Case<IntegerAttr>([&](auto intAttr) {
318  llvm::Type::getInt32Ty(builder.getContext()),
319  intAttr.getInt()));
320  })
321  .Case<ArrayAttr>([&](auto arrayAttr) {
322  return convertModuleFlagValue(flagAttr.getKey().getValue(),
323  arrayAttr, builder,
324  moduleTranslation);
325  })
326  .Default([](auto) { return nullptr; });
327 
328  assert(valueMetadata && "expected valid metadata");
329  llvmModule->addModuleFlag(
330  convertModFlagBehaviorToLLVM(flagAttr.getBehavior()),
331  flagAttr.getKey().getValue(), valueMetadata);
332  }
333 }
334 
335 static LogicalResult
336 convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
337  LLVM::ModuleTranslation &moduleTranslation) {
338 
339  llvm::IRBuilder<>::FastMathFlagGuard fmfGuard(builder);
340  if (auto fmf = dyn_cast<FastmathFlagsInterface>(opInst))
341  builder.setFastMathFlags(getFastmathFlags(fmf));
342 
343 #include "mlir/Dialect/LLVMIR/LLVMConversions.inc"
344 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicConversions.inc"
345 
346  // Emit function calls. If the "callee" attribute is present, this is a
347  // direct function call and we also need to look up the remapped function
348  // itself. Otherwise, this is an indirect call and the callee is the first
349  // operand, look it up as a normal value.
350  if (auto callOp = dyn_cast<LLVM::CallOp>(opInst)) {
351  auto operands = moduleTranslation.lookupValues(callOp.getCalleeOperands());
353  convertOperandBundles(callOp.getOpBundleOperands(),
354  callOp.getOpBundleTags(), moduleTranslation);
355  ArrayRef<llvm::Value *> operandsRef(operands);
356  llvm::CallInst *call;
357  if (auto attr = callOp.getCalleeAttr()) {
358  call =
359  builder.CreateCall(moduleTranslation.lookupFunction(attr.getValue()),
360  operandsRef, opBundles);
361  } else {
362  llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
363  moduleTranslation.convertType(callOp.getCalleeFunctionType()));
364  call = builder.CreateCall(calleeType, operandsRef.front(),
365  operandsRef.drop_front(), opBundles);
366  }
367  call->setCallingConv(convertCConvToLLVM(callOp.getCConv()));
368  call->setTailCallKind(convertTailCallKindToLLVM(callOp.getTailCallKind()));
369  if (callOp.getConvergentAttr())
370  call->addFnAttr(llvm::Attribute::Convergent);
371  if (callOp.getNoUnwindAttr())
372  call->addFnAttr(llvm::Attribute::NoUnwind);
373  if (callOp.getWillReturnAttr())
374  call->addFnAttr(llvm::Attribute::WillReturn);
375  if (callOp.getNoInlineAttr())
376  call->addFnAttr(llvm::Attribute::NoInline);
377  if (callOp.getAlwaysInlineAttr())
378  call->addFnAttr(llvm::Attribute::AlwaysInline);
379  if (callOp.getInlineHintAttr())
380  call->addFnAttr(llvm::Attribute::InlineHint);
381 
382  if (failed(convertParameterAndResultAttrs(callOp, call, moduleTranslation)))
383  return failure();
384 
385  if (MemoryEffectsAttr memAttr = callOp.getMemoryEffectsAttr()) {
386  llvm::MemoryEffects memEffects =
387  llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
388  convertModRefInfoToLLVM(memAttr.getArgMem())) |
389  llvm::MemoryEffects(
390  llvm::MemoryEffects::Location::InaccessibleMem,
391  convertModRefInfoToLLVM(memAttr.getInaccessibleMem())) |
392  llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
393  convertModRefInfoToLLVM(memAttr.getOther()));
394  call->setMemoryEffects(memEffects);
395  }
396 
397  moduleTranslation.setAccessGroupsMetadata(callOp, call);
398  moduleTranslation.setAliasScopeMetadata(callOp, call);
399  moduleTranslation.setTBAAMetadata(callOp, call);
400  // If the called function has a result, remap the corresponding value. Note
401  // that LLVM IR dialect CallOp has either 0 or 1 result.
402  if (opInst.getNumResults() != 0)
403  moduleTranslation.mapValue(opInst.getResult(0), call);
404  // Check that LLVM call returns void for 0-result functions.
405  else if (!call->getType()->isVoidTy())
406  return failure();
407  moduleTranslation.mapCall(callOp, call);
408  return success();
409  }
410 
411  if (auto inlineAsmOp = dyn_cast<LLVM::InlineAsmOp>(opInst)) {
412  // TODO: refactor function type creation which usually occurs in std-LLVM
413  // conversion.
414  SmallVector<Type, 8> operandTypes;
415  llvm::append_range(operandTypes, inlineAsmOp.getOperands().getTypes());
416 
417  Type resultType;
418  if (inlineAsmOp.getNumResults() == 0) {
419  resultType = LLVM::LLVMVoidType::get(&moduleTranslation.getContext());
420  } else {
421  assert(inlineAsmOp.getNumResults() == 1);
422  resultType = inlineAsmOp.getResultTypes()[0];
423  }
424  auto ft = LLVM::LLVMFunctionType::get(resultType, operandTypes);
425  llvm::InlineAsm *inlineAsmInst =
426  inlineAsmOp.getAsmDialect()
428  static_cast<llvm::FunctionType *>(
429  moduleTranslation.convertType(ft)),
430  inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
431  inlineAsmOp.getHasSideEffects(),
432  inlineAsmOp.getIsAlignStack(),
433  convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
434  : llvm::InlineAsm::get(static_cast<llvm::FunctionType *>(
435  moduleTranslation.convertType(ft)),
436  inlineAsmOp.getAsmString(),
437  inlineAsmOp.getConstraints(),
438  inlineAsmOp.getHasSideEffects(),
439  inlineAsmOp.getIsAlignStack());
440  llvm::CallInst *inst = builder.CreateCall(
441  inlineAsmInst,
442  moduleTranslation.lookupValues(inlineAsmOp.getOperands()));
443  if (auto maybeOperandAttrs = inlineAsmOp.getOperandAttrs()) {
444  llvm::AttributeList attrList;
445  for (const auto &it : llvm::enumerate(*maybeOperandAttrs)) {
446  Attribute attr = it.value();
447  if (!attr)
448  continue;
449  DictionaryAttr dAttr = cast<DictionaryAttr>(attr);
450  TypeAttr tAttr =
451  cast<TypeAttr>(dAttr.get(InlineAsmOp::getElementTypeAttrName()));
452  llvm::AttrBuilder b(moduleTranslation.getLLVMContext());
453  llvm::Type *ty = moduleTranslation.convertType(tAttr.getValue());
454  b.addTypeAttr(llvm::Attribute::ElementType, ty);
455  // shift to account for the returned value (this is always 1 aggregate
456  // value in LLVM).
457  int shift = (opInst.getNumResults() > 0) ? 1 : 0;
458  attrList = attrList.addAttributesAtIndex(
459  moduleTranslation.getLLVMContext(), it.index() + shift, b);
460  }
461  inst->setAttributes(attrList);
462  }
463 
464  if (opInst.getNumResults() != 0)
465  moduleTranslation.mapValue(opInst.getResult(0), inst);
466  return success();
467  }
468 
469  if (auto invOp = dyn_cast<LLVM::InvokeOp>(opInst)) {
470  auto operands = moduleTranslation.lookupValues(invOp.getCalleeOperands());
472  convertOperandBundles(invOp.getOpBundleOperands(),
473  invOp.getOpBundleTags(), moduleTranslation);
474  ArrayRef<llvm::Value *> operandsRef(operands);
475  llvm::InvokeInst *result;
476  if (auto attr = opInst.getAttrOfType<FlatSymbolRefAttr>("callee")) {
477  result = builder.CreateInvoke(
478  moduleTranslation.lookupFunction(attr.getValue()),
479  moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
480  moduleTranslation.lookupBlock(invOp.getSuccessor(1)), operandsRef,
481  opBundles);
482  } else {
483  llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
484  moduleTranslation.convertType(invOp.getCalleeFunctionType()));
485  result = builder.CreateInvoke(
486  calleeType, operandsRef.front(),
487  moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
488  moduleTranslation.lookupBlock(invOp.getSuccessor(1)),
489  operandsRef.drop_front(), opBundles);
490  }
491  result->setCallingConv(convertCConvToLLVM(invOp.getCConv()));
492  if (failed(
493  convertParameterAndResultAttrs(invOp, result, moduleTranslation)))
494  return failure();
495  moduleTranslation.mapBranch(invOp, result);
496  // InvokeOp can only have 0 or 1 result
497  if (invOp->getNumResults() != 0) {
498  moduleTranslation.mapValue(opInst.getResult(0), result);
499  return success();
500  }
501  return success(result->getType()->isVoidTy());
502  }
503 
504  if (auto lpOp = dyn_cast<LLVM::LandingpadOp>(opInst)) {
505  llvm::Type *ty = moduleTranslation.convertType(lpOp.getType());
506  llvm::LandingPadInst *lpi =
507  builder.CreateLandingPad(ty, lpOp.getNumOperands());
508  lpi->setCleanup(lpOp.getCleanup());
509 
510  // Add clauses
511  for (llvm::Value *operand :
512  moduleTranslation.lookupValues(lpOp.getOperands())) {
513  // All operands should be constant - checked by verifier
514  if (auto *constOperand = dyn_cast<llvm::Constant>(operand))
515  lpi->addClause(constOperand);
516  }
517  moduleTranslation.mapValue(lpOp.getResult(), lpi);
518  return success();
519  }
520 
521  // Emit branches. We need to look up the remapped blocks and ignore the
522  // block arguments that were transformed into PHI nodes.
523  if (auto brOp = dyn_cast<LLVM::BrOp>(opInst)) {
524  llvm::BranchInst *branch =
525  builder.CreateBr(moduleTranslation.lookupBlock(brOp.getSuccessor()));
526  moduleTranslation.mapBranch(&opInst, branch);
527  moduleTranslation.setLoopMetadata(&opInst, branch);
528  return success();
529  }
530  if (auto condbrOp = dyn_cast<LLVM::CondBrOp>(opInst)) {
531  llvm::BranchInst *branch = builder.CreateCondBr(
532  moduleTranslation.lookupValue(condbrOp.getOperand(0)),
533  moduleTranslation.lookupBlock(condbrOp.getSuccessor(0)),
534  moduleTranslation.lookupBlock(condbrOp.getSuccessor(1)));
535  moduleTranslation.mapBranch(&opInst, branch);
536  moduleTranslation.setLoopMetadata(&opInst, branch);
537  return success();
538  }
539  if (auto switchOp = dyn_cast<LLVM::SwitchOp>(opInst)) {
540  llvm::SwitchInst *switchInst = builder.CreateSwitch(
541  moduleTranslation.lookupValue(switchOp.getValue()),
542  moduleTranslation.lookupBlock(switchOp.getDefaultDestination()),
543  switchOp.getCaseDestinations().size());
544 
545  // Handle switch with zero cases.
546  if (!switchOp.getCaseValues())
547  return success();
548 
549  auto *ty = llvm::cast<llvm::IntegerType>(
550  moduleTranslation.convertType(switchOp.getValue().getType()));
551  for (auto i :
552  llvm::zip(llvm::cast<DenseIntElementsAttr>(*switchOp.getCaseValues()),
553  switchOp.getCaseDestinations()))
554  switchInst->addCase(
555  llvm::ConstantInt::get(ty, std::get<0>(i).getLimitedValue()),
556  moduleTranslation.lookupBlock(std::get<1>(i)));
557 
558  moduleTranslation.mapBranch(&opInst, switchInst);
559  return success();
560  }
561  if (auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(opInst)) {
562  llvm::IndirectBrInst *indBr = builder.CreateIndirectBr(
563  moduleTranslation.lookupValue(indBrOp.getAddr()),
564  indBrOp->getNumSuccessors());
565  for (auto *succ : indBrOp.getSuccessors())
566  indBr->addDestination(moduleTranslation.lookupBlock(succ));
567  moduleTranslation.mapBranch(&opInst, indBr);
568  return success();
569  }
570 
571  // Emit addressof. We need to look up the global value referenced by the
572  // operation and store it in the MLIR-to-LLVM value mapping. This does not
573  // emit any LLVM instruction.
574  if (auto addressOfOp = dyn_cast<LLVM::AddressOfOp>(opInst)) {
575  LLVM::GlobalOp global =
576  addressOfOp.getGlobal(moduleTranslation.symbolTable());
577  LLVM::LLVMFuncOp function =
578  addressOfOp.getFunction(moduleTranslation.symbolTable());
579  LLVM::AliasOp alias = addressOfOp.getAlias(moduleTranslation.symbolTable());
580 
581  // The verifier should not have allowed this.
582  assert((global || function || alias) &&
583  "referencing an undefined global, function, or alias");
584 
585  llvm::Value *llvmValue = nullptr;
586  if (global)
587  llvmValue = moduleTranslation.lookupGlobal(global);
588  else if (alias)
589  llvmValue = moduleTranslation.lookupAlias(alias);
590  else
591  llvmValue = moduleTranslation.lookupFunction(function.getName());
592 
593  moduleTranslation.mapValue(addressOfOp.getResult(), llvmValue);
594  return success();
595  }
596 
597  // Emit dso_local_equivalent. We need to look up the global value referenced
598  // by the operation and store it in the MLIR-to-LLVM value mapping.
599  if (auto dsoLocalEquivalentOp =
600  dyn_cast<LLVM::DSOLocalEquivalentOp>(opInst)) {
601  LLVM::LLVMFuncOp function =
602  dsoLocalEquivalentOp.getFunction(moduleTranslation.symbolTable());
603  LLVM::AliasOp alias =
604  dsoLocalEquivalentOp.getAlias(moduleTranslation.symbolTable());
605 
606  // The verifier should not have allowed this.
607  assert((function || alias) &&
608  "referencing an undefined function, or alias");
609 
610  llvm::Value *llvmValue = nullptr;
611  if (alias)
612  llvmValue = moduleTranslation.lookupAlias(alias);
613  else
614  llvmValue = moduleTranslation.lookupFunction(function.getName());
615 
616  moduleTranslation.mapValue(
617  dsoLocalEquivalentOp.getResult(),
618  llvm::DSOLocalEquivalent::get(cast<llvm::GlobalValue>(llvmValue)));
619  return success();
620  }
621 
622  // Emit blockaddress. We first need to find the LLVM block referenced by this
623  // operation and then create a LLVM block address for it.
624  if (auto blockAddressOp = dyn_cast<LLVM::BlockAddressOp>(opInst)) {
625  // getBlockTagOp() walks a function to search for block labels. Check
626  // whether it's in cache first.
627  BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
628  BlockTagOp blockTagOp = moduleTranslation.lookupBlockTag(blockAddressAttr);
629  if (!blockTagOp) {
630  blockTagOp = blockAddressOp.getBlockTagOp();
631  moduleTranslation.mapBlockTag(blockAddressAttr, blockTagOp);
632  }
633 
634  llvm::Value *llvmValue = nullptr;
635  StringRef fnName = blockAddressAttr.getFunction().getValue();
636  if (llvm::BasicBlock *llvmBlock =
637  moduleTranslation.lookupBlock(blockTagOp->getBlock())) {
638  llvm::Function *llvmFn = moduleTranslation.lookupFunction(fnName);
639  llvmValue = llvm::BlockAddress::get(llvmFn, llvmBlock);
640  } else {
641  // The matching LLVM block is not yet emitted, a placeholder is created
642  // in its place. When the LLVM block is emitted later in translation,
643  // the llvmValue is replaced with the actual llvm::BlockAddress.
644  // A GlobalVariable is chosen as placeholder because in general LLVM
645  // constants are uniqued and are not proper for RAUW, since that could
646  // harm unrelated uses of the constant.
647  llvmValue = new llvm::GlobalVariable(
648  *moduleTranslation.getLLVMModule(),
649  llvm::PointerType::getUnqual(moduleTranslation.getLLVMContext()),
650  /*isConstant=*/true, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
651  /*Initializer=*/nullptr,
652  Twine("__mlir_block_address_")
653  .concat(Twine(fnName))
654  .concat(Twine((uint64_t)blockAddressOp.getOperation())));
655  moduleTranslation.mapUnresolvedBlockAddress(blockAddressOp, llvmValue);
656  }
657 
658  moduleTranslation.mapValue(blockAddressOp.getResult(), llvmValue);
659  return success();
660  }
661 
662  // Emit block label. If this label is seen before BlockAddressOp is
663  // translated, go ahead and already map it.
664  if (auto blockTagOp = dyn_cast<LLVM::BlockTagOp>(opInst)) {
665  auto funcOp = blockTagOp->getParentOfType<LLVMFuncOp>();
666  BlockAddressAttr blockAddressAttr = BlockAddressAttr::get(
667  &moduleTranslation.getContext(),
668  FlatSymbolRefAttr::get(&moduleTranslation.getContext(),
669  funcOp.getName()),
670  blockTagOp.getTag());
671  moduleTranslation.mapBlockTag(blockAddressAttr, blockTagOp);
672  return success();
673  }
674 
675  return failure();
676 }
677 
678 namespace {
679 /// Implementation of the dialect interface that converts operations belonging
680 /// to the LLVM dialect to LLVM IR.
681 class LLVMDialectLLVMIRTranslationInterface
683 public:
685 
686  /// Translates the given operation to LLVM IR using the provided IR builder
687  /// and saving the state in `moduleTranslation`.
688  LogicalResult
689  convertOperation(Operation *op, llvm::IRBuilderBase &builder,
690  LLVM::ModuleTranslation &moduleTranslation) const final {
691  return convertOperationImpl(*op, builder, moduleTranslation);
692  }
693 };
694 } // namespace
695 
697  registry.insert<LLVM::LLVMDialect>();
698  registry.addExtension(+[](MLIRContext *ctx, LLVM::LLVMDialect *dialect) {
699  dialect->addInterfaces<LLVMDialectLLVMIRTranslationInterface>();
700  });
701 }
702 
704  DialectRegistry registry;
706  context.appendDialectRegistry(registry);
707 }
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 LogicalResult convertParameterAndResultAttrs(mlir::Location loc, ArrayAttr argAttrsArray, ArrayAttr resAttrsArray, llvm::CallBase *call, 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 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.
Base class for dialect interfaces providing translation to LLVM IR.
Implementation class for module translation.
void mapUnresolvedBlockAddress(BlockAddressOp op, llvm::Value *cst)
Maps a blockaddress operation to its corresponding placeholder LLVM value.
void mapBlockTag(BlockAddressAttr attr, BlockTagOp blockTag)
Maps a blockaddress operation to its corresponding placeholder LLVM value.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
void mapCall(Operation *mlir, llvm::CallInst *llvm)
Stores a mapping between an MLIR call operation and a corresponding LLVM call instruction.
FailureOr< llvm::AttrBuilder > convertParameterAttrs(mlir::Location loc, DictionaryAttr paramAttrs)
Translates parameter attributes of a call and adds them to the returned AttrBuilder.
void mapBranch(Operation *mlir, llvm::Instruction *llvm)
Stores the mapping between an MLIR operation with successors and a corresponding LLVM IR instruction.
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.
SymbolTableCollection & symbolTable()
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::GlobalValue * lookupAlias(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global alias va...
void setTBAAMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
Sets LLVM TBAA metadata for memory operations that have TBAA attributes.
BlockTagOp lookupBlockTag(BlockAddressAttr attr) const
Finds an MLIR block that corresponds to the given MLIR call operation.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
void setAliasScopeMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
void setAccessGroupsMetadata(AccessGroupOpInterface op, llvm::Instruction *inst)
MLIRContext & getContext()
Returns the MLIR context of the module being translated.
void mapValue(Value mlir, llvm::Value *llvm)
Stores the mapping between an MLIR value and its LLVM IR counterpart.
void setLoopMetadata(Operation *op, llvm::Instruction *inst)
Sets LLVM loop metadata for branch operations that have a loop annotation attribute.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:66
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
void appendDialectRegistry(const DialectRegistry &registry)
Append the contents of the given dialect registry to the registry associated with this context.
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
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.
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:2336
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...