MLIR  19.0.0git
LLVMIRToLLVMTranslation.cpp
Go to the documentation of this file.
1 //===- LLVMIRToLLVMTranslation.cpp - Translate LLVM IR to LLVM dialect ----===//
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 LLVM IR and the MLIR LLVM dialect.
10 //
11 //===----------------------------------------------------------------------===//
12 
16 #include "mlir/Support/LLVM.h"
18 
19 #include "llvm/ADT/PostOrderIterator.h"
20 #include "llvm/ADT/ScopeExit.h"
21 #include "llvm/ADT/StringSet.h"
22 #include "llvm/ADT/TypeSwitch.h"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/IR/InlineAsm.h"
25 #include "llvm/IR/Instructions.h"
26 #include "llvm/IR/IntrinsicInst.h"
27 #include "llvm/Support/ModRef.h"
28 
29 using namespace mlir;
30 using namespace mlir::LLVM;
31 using namespace mlir::LLVM::detail;
32 
33 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
34 
35 /// Returns true if the LLVM IR intrinsic is convertible to an MLIR LLVM dialect
36 /// intrinsic. Returns false otherwise.
38  static const DenseSet<unsigned> convertibleIntrinsics = {
39 #include "mlir/Dialect/LLVMIR/LLVMConvertibleLLVMIRIntrinsics.inc"
40  };
41  return convertibleIntrinsics.contains(id);
42 }
43 
44 /// Returns the list of LLVM IR intrinsic identifiers that are convertible to
45 /// MLIR LLVM dialect intrinsics.
47  static const SmallVector<unsigned> convertibleIntrinsics = {
48 #include "mlir/Dialect/LLVMIR/LLVMConvertibleLLVMIRIntrinsics.inc"
49  };
50  return convertibleIntrinsics;
51 }
52 
53 /// Converts the LLVM intrinsic to an MLIR LLVM dialect operation if a
54 /// conversion exits. Returns failure otherwise.
56  llvm::CallInst *inst,
57  LLVM::ModuleImport &moduleImport) {
58  llvm::Intrinsic::ID intrinsicID = inst->getIntrinsicID();
59 
60  // Check if the intrinsic is convertible to an MLIR dialect counterpart and
61  // copy the arguments to an an LLVM operands array reference for conversion.
62  if (isConvertibleIntrinsic(intrinsicID)) {
63  SmallVector<llvm::Value *> args(inst->args());
64  ArrayRef<llvm::Value *> llvmOperands(args);
65 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicFromLLVMIRConversions.inc"
66  }
67 
68  return failure();
69 }
70 
71 /// Returns the list of LLVM IR metadata kinds that are convertible to MLIR LLVM
72 /// dialect attributes.
74  static const SmallVector<unsigned> convertibleMetadata = {
75  llvm::LLVMContext::MD_prof, llvm::LLVMContext::MD_tbaa,
76  llvm::LLVMContext::MD_access_group, llvm::LLVMContext::MD_loop,
77  llvm::LLVMContext::MD_noalias, llvm::LLVMContext::MD_alias_scope};
78  return convertibleMetadata;
79 }
80 
81 /// Converts the given profiling metadata `node` to an MLIR profiling attribute
82 /// and attaches it to the imported operation if the translation succeeds.
83 /// Returns failure otherwise.
84 static LogicalResult setProfilingAttr(OpBuilder &builder, llvm::MDNode *node,
85  Operation *op,
86  LLVM::ModuleImport &moduleImport) {
87  // Return failure for empty metadata nodes since there is nothing to import.
88  if (!node->getNumOperands())
89  return failure();
90 
91  auto *name = dyn_cast<llvm::MDString>(node->getOperand(0));
92  if (!name)
93  return failure();
94 
95  // Handle function entry count metadata.
96  if (name->getString().equals("function_entry_count")) {
97 
98  // TODO support function entry count metadata with GUID fields.
99  if (node->getNumOperands() != 2)
100  return failure();
101 
102  llvm::ConstantInt *entryCount =
103  llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(1));
104  if (!entryCount)
105  return failure();
106  if (auto funcOp = dyn_cast<LLVMFuncOp>(op)) {
107  funcOp.setFunctionEntryCount(entryCount->getZExtValue());
108  return success();
109  }
110  return op->emitWarning()
111  << "expected function_entry_count to be attached to a function";
112  }
113 
114  if (!name->getString().equals("branch_weights"))
115  return failure();
116 
117  // Handle branch weights metadata.
118  SmallVector<int32_t> branchWeights;
119  branchWeights.reserve(node->getNumOperands() - 1);
120  for (unsigned i = 1, e = node->getNumOperands(); i != e; ++i) {
121  llvm::ConstantInt *branchWeight =
122  llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(i));
123  if (!branchWeight)
124  return failure();
125  branchWeights.push_back(branchWeight->getZExtValue());
126  }
127 
128  if (auto iface = dyn_cast<BranchWeightOpInterface>(op)) {
129  iface.setBranchWeights(builder.getDenseI32ArrayAttr(branchWeights));
130  return success();
131  }
132  return failure();
133 }
134 
135 /// Searches for the attribute that maps to the given TBAA metadata `node` and
136 /// attaches it to the imported operation if the lookup succeeds. Returns
137 /// failure otherwise.
138 static LogicalResult setTBAAAttr(const llvm::MDNode *node, Operation *op,
139  LLVM::ModuleImport &moduleImport) {
140  Attribute tbaaTagSym = moduleImport.lookupTBAAAttr(node);
141  if (!tbaaTagSym)
142  return failure();
143 
144  auto iface = dyn_cast<AliasAnalysisOpInterface>(op);
145  if (!iface)
146  return failure();
147 
148  iface.setTBAATags(ArrayAttr::get(iface.getContext(), tbaaTagSym));
149  return success();
150 }
151 
152 /// Looks up all the access group attributes that map to the access group nodes
153 /// starting from the access group metadata `node`, and attaches all of them to
154 /// the imported operation if the lookups succeed. Returns failure otherwise.
155 static LogicalResult setAccessGroupsAttr(const llvm::MDNode *node,
156  Operation *op,
157  LLVM::ModuleImport &moduleImport) {
159  moduleImport.lookupAccessGroupAttrs(node);
160  if (failed(accessGroups))
161  return failure();
162 
163  auto iface = dyn_cast<AccessGroupOpInterface>(op);
164  if (!iface)
165  return failure();
166 
167  iface.setAccessGroups(ArrayAttr::get(
168  iface.getContext(), llvm::to_vector_of<Attribute>(*accessGroups)));
169  return success();
170 }
171 
172 /// Converts the given loop metadata node to an MLIR loop annotation attribute
173 /// and attaches it to the imported operation if the translation succeeds.
174 /// Returns failure otherwise.
175 static LogicalResult setLoopAttr(const llvm::MDNode *node, Operation *op,
176  LLVM::ModuleImport &moduleImport) {
177  LoopAnnotationAttr attr =
178  moduleImport.translateLoopAnnotationAttr(node, op->getLoc());
179  if (!attr)
180  return failure();
181 
183  .Case<LLVM::BrOp, LLVM::CondBrOp>([&](auto branchOp) {
184  branchOp.setLoopAnnotationAttr(attr);
185  return success();
186  })
187  .Default([](auto) { return failure(); });
188 }
189 
190 /// Looks up all the alias scope attributes that map to the alias scope nodes
191 /// starting from the alias scope metadata `node`, and attaches all of them to
192 /// the imported operation if the lookups succeed. Returns failure otherwise.
193 static LogicalResult setAliasScopesAttr(const llvm::MDNode *node, Operation *op,
194  LLVM::ModuleImport &moduleImport) {
196  moduleImport.lookupAliasScopeAttrs(node);
197  if (failed(aliasScopes))
198  return failure();
199 
200  auto iface = dyn_cast<AliasAnalysisOpInterface>(op);
201  if (!iface)
202  return failure();
203 
204  iface.setAliasScopes(ArrayAttr::get(
205  iface.getContext(), llvm::to_vector_of<Attribute>(*aliasScopes)));
206  return success();
207 }
208 
209 /// Looks up all the alias scope attributes that map to the alias scope nodes
210 /// starting from the noalias metadata `node`, and attaches all of them to the
211 /// imported operation if the lookups succeed. Returns failure otherwise.
212 static LogicalResult setNoaliasScopesAttr(const llvm::MDNode *node,
213  Operation *op,
214  LLVM::ModuleImport &moduleImport) {
216  moduleImport.lookupAliasScopeAttrs(node);
217  if (failed(noAliasScopes))
218  return failure();
219 
220  auto iface = dyn_cast<AliasAnalysisOpInterface>(op);
221  if (!iface)
222  return failure();
223 
224  iface.setNoAliasScopes(ArrayAttr::get(
225  iface.getContext(), llvm::to_vector_of<Attribute>(*noAliasScopes)));
226  return success();
227 }
228 
229 namespace {
230 
231 /// Implementation of the dialect interface that converts operations belonging
232 /// to the LLVM dialect to LLVM IR.
233 class LLVMDialectLLVMIRImportInterface : public LLVMImportDialectInterface {
234 public:
236 
237  /// Converts the LLVM intrinsic to an MLIR LLVM dialect operation if a
238  /// conversion exits. Returns failure otherwise.
239  LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
240  LLVM::ModuleImport &moduleImport) const final {
241  return convertIntrinsicImpl(builder, inst, moduleImport);
242  }
243 
244  /// Attaches the given LLVM metadata to the imported operation if a conversion
245  /// to an LLVM dialect attribute exists and succeeds. Returns failure
246  /// otherwise.
247  LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind,
248  llvm::MDNode *node, Operation *op,
249  LLVM::ModuleImport &moduleImport) const final {
250  // Call metadata specific handlers.
251  if (kind == llvm::LLVMContext::MD_prof)
252  return setProfilingAttr(builder, node, op, moduleImport);
253  if (kind == llvm::LLVMContext::MD_tbaa)
254  return setTBAAAttr(node, op, moduleImport);
255  if (kind == llvm::LLVMContext::MD_access_group)
256  return setAccessGroupsAttr(node, op, moduleImport);
257  if (kind == llvm::LLVMContext::MD_loop)
258  return setLoopAttr(node, op, moduleImport);
259  if (kind == llvm::LLVMContext::MD_alias_scope)
260  return setAliasScopesAttr(node, op, moduleImport);
261  if (kind == llvm::LLVMContext::MD_noalias)
262  return setNoaliasScopesAttr(node, op, moduleImport);
263 
264  // A handler for a supported metadata kind is missing.
265  llvm_unreachable("unknown metadata type");
266  }
267 
268  /// Returns the list of LLVM IR intrinsic identifiers that are convertible to
269  /// MLIR LLVM dialect intrinsics.
270  ArrayRef<unsigned> getSupportedIntrinsics() const final {
272  }
273 
274  /// Returns the list of LLVM IR metadata kinds that are convertible to MLIR
275  /// LLVM dialect attributes.
276  ArrayRef<unsigned> getSupportedMetadata() const final {
277  return getSupportedMetadataImpl();
278  }
279 };
280 } // namespace
281 
283  registry.insert<LLVM::LLVMDialect>();
284  registry.addExtension(+[](MLIRContext *ctx, LLVM::LLVMDialect *dialect) {
285  dialect->addInterfaces<LLVMDialectLLVMIRImportInterface>();
286  });
287 }
288 
290  DialectRegistry registry;
291  registerLLVMDialectImport(registry);
292  context.appendDialectRegistry(registry);
293 }
static ArrayRef< unsigned > getSupportedMetadataImpl()
Returns the list of LLVM IR metadata kinds that are convertible to MLIR LLVM dialect attributes.
static LogicalResult setLoopAttr(const llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport)
Converts the given loop metadata node to an MLIR loop annotation attribute and attaches it to the imp...
static ArrayRef< unsigned > getSupportedIntrinsicsImpl()
Returns the list of LLVM IR intrinsic identifiers that are convertible to MLIR LLVM dialect intrinsic...
static LogicalResult setTBAAAttr(const llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport)
Searches for the attribute that maps to the given TBAA metadata node and attaches it to the imported ...
static LogicalResult setProfilingAttr(OpBuilder &builder, llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport)
Converts the given profiling metadata node to an MLIR profiling attribute and attaches it to the impo...
static LogicalResult setAliasScopesAttr(const llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport)
Looks up all the alias scope attributes that map to the alias scope nodes starting from the alias sco...
static LogicalResult setNoaliasScopesAttr(const llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport)
Looks up all the alias scope attributes that map to the alias scope nodes starting from the noalias m...
static bool isConvertibleIntrinsic(llvm::Intrinsic::ID id)
Returns true if the LLVM IR intrinsic is convertible to an MLIR LLVM dialect intrinsic.
static LogicalResult convertIntrinsicImpl(OpBuilder &odsBuilder, llvm::CallInst *inst, LLVM::ModuleImport &moduleImport)
Converts the LLVM intrinsic to an MLIR LLVM dialect operation if a conversion exits.
static LogicalResult setAccessGroupsAttr(const llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport)
Looks up all the access group attributes that map to the access group nodes starting from the access ...
Attributes are known-constant values of operations.
Definition: Attributes.h:25
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
Definition: Builders.cpp:179
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
void addExtension(std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
This class provides support for representing a failure result, or a valid value of type T.
Definition: LogicalResult.h:78
Base class for dialect interfaces used to import LLVM IR.
LLVMImportDialectInterface(Dialect *dialect)
Module import implementation class that provides methods to import globals and functions from an LLVM...
Definition: ModuleImport.h:47
Attribute lookupTBAAAttr(const llvm::MDNode *node) const
Returns the MLIR attribute mapped to the given LLVM TBAA metadata node.
Definition: ModuleImport.h:206
FailureOr< SmallVector< AliasScopeAttr > > lookupAliasScopeAttrs(const llvm::MDNode *node) const
Returns the alias scope attributes that map to the alias scope nodes starting from the metadata node.
LoopAnnotationAttr translateLoopAnnotationAttr(const llvm::MDNode *node, Location loc) const
Returns the loop annotation attribute that corresponds to the given LLVM loop metadata node.
FailureOr< SmallVector< AccessGroupAttr > > lookupAccessGroupAttrs(const llvm::MDNode *node) const
Returns the access group attributes that map to the access group nodes starting from the access group...
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 helps build Operations.
Definition: Builders.h:209
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
Definition: Operation.cpp:280
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
void registerLLVMDialectImport(DialectRegistry &registry)
Registers the LLVM dialect and its import from 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...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26