MLIR  21.0.0git
LLVMImportInterface.h
Go to the documentation of this file.
1 //===- LLVMImportInterface.h - Import from LLVM interface -------*- C++ -*-===//
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 header file defines dialect interfaces for the LLVM IR import.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_TARGET_LLVMIR_LLVMIMPORTINTERFACE_H
14 #define MLIR_TARGET_LLVMIR_LLVMIMPORTINTERFACE_H
15 
17 #include "mlir/IR/Builders.h"
19 #include "mlir/IR/Diagnostics.h"
21 #include "mlir/IR/Location.h"
22 #include "llvm/IR/Instruction.h"
23 #include "llvm/IR/Instructions.h"
24 #include "llvm/Support/FormatVariadic.h"
25 
26 namespace llvm {
27 class IRBuilderBase;
28 } // namespace llvm
29 
30 namespace mlir {
31 namespace LLVM {
32 class ModuleImport;
33 } // namespace LLVM
34 
35 /// Base class for dialect interfaces used to import LLVM IR. Dialects that can
36 /// be imported should provide an implementation of this interface for the
37 /// supported intrinsics. The interface may be implemented in a separate library
38 /// to avoid the "main" dialect library depending on LLVM IR. The interface can
39 /// be attached using the delayed registration mechanism available in
40 /// DialectRegistry.
42  : public DialectInterface::Base<LLVMImportDialectInterface> {
43 public:
44  LLVMImportDialectInterface(Dialect *dialect) : Base(dialect) {}
45 
46  /// Hook for derived dialect interfaces to implement the import of
47  /// intrinsics into MLIR.
48  virtual LogicalResult
49  convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
50  LLVM::ModuleImport &moduleImport) const {
51  return failure();
52  }
53 
54  /// Hook for derived dialect interfaces to implement the import of
55  /// instructions into MLIR.
56  virtual LogicalResult
57  convertInstruction(OpBuilder &builder, llvm::Instruction *inst,
58  ArrayRef<llvm::Value *> llvmOperands,
59  LLVM::ModuleImport &moduleImport) const {
60  return failure();
61  }
62 
63  /// Hook for derived dialect interfaces to implement the import of metadata
64  /// into MLIR. Attaches the converted metadata kind and node to the provided
65  /// operation.
66  virtual LogicalResult
67  setMetadataAttrs(OpBuilder &builder, unsigned kind, llvm::MDNode *node,
68  Operation *op, LLVM::ModuleImport &moduleImport) const {
69  return failure();
70  }
71 
72  /// Hook for derived dialect interfaces to publish the supported intrinsics.
73  /// As every LLVM IR intrinsic has a unique integer identifier, the function
74  /// returns the list of supported intrinsic identifiers.
75  virtual ArrayRef<unsigned> getSupportedIntrinsics() const { return {}; }
76 
77  /// Hook for derived dialect interfaces to publish the supported instructions.
78  /// As every LLVM IR instruction has a unique integer identifier, the function
79  /// returns the list of supported instruction identifiers. These identifiers
80  /// will then be used to match LLVM instructions to the appropriate import
81  /// interface and `convertInstruction` method. It is an error to have multiple
82  /// interfaces overriding the same instruction.
83  virtual ArrayRef<unsigned> getSupportedInstructions() const { return {}; }
84 
85  /// Hook for derived dialect interfaces to publish the supported metadata
86  /// kinds. As every metadata kind has a unique integer identifier, the
87  /// function returns the list of supported metadata identifiers. `ctx` can be
88  /// used to obtain IDs of metadata kinds that do not have a fixed static one.
89  virtual ArrayRef<unsigned>
90  getSupportedMetadata(llvm::LLVMContext &ctx) const {
91  return {};
92  }
93 };
94 
95 /// Interface collection for the import of LLVM IR that dispatches to a concrete
96 /// dialect interface implementation. Queries the dialect interfaces to obtain a
97 /// list of the supported LLVM IR constructs and then builds a mapping for the
98 /// efficient dispatch.
100  : public DialectInterfaceCollection<LLVMImportDialectInterface> {
101 public:
102  using Base::Base;
103 
104  /// Queries all registered dialect interfaces for the supported LLVM IR
105  /// intrinsic and metadata kinds and builds the dispatch tables for the
106  /// conversion. Returns failure if multiple dialect interfaces translate the
107  /// same LLVM IR intrinsic.
108  LogicalResult initializeImport(llvm::LLVMContext &llvmContext) {
109  for (const LLVMImportDialectInterface &iface : *this) {
110  // Verify the supported intrinsics have not been mapped before.
111  const auto *intrinsicIt =
112  llvm::find_if(iface.getSupportedIntrinsics(), [&](unsigned id) {
113  return intrinsicToDialect.count(id);
114  });
115  if (intrinsicIt != iface.getSupportedIntrinsics().end()) {
116  return emitError(
117  UnknownLoc::get(iface.getContext()),
118  llvm::formatv(
119  "expected unique conversion for intrinsic ({0}), but "
120  "got conflicting {1} and {2} conversions",
121  *intrinsicIt, iface.getDialect()->getNamespace(),
122  intrinsicToDialect.lookup(*intrinsicIt)->getNamespace()));
123  }
124  const auto *instructionIt =
125  llvm::find_if(iface.getSupportedInstructions(), [&](unsigned id) {
126  return instructionToDialect.count(id);
127  });
128  if (instructionIt != iface.getSupportedInstructions().end()) {
129  return emitError(
130  UnknownLoc::get(iface.getContext()),
131  llvm::formatv(
132  "expected unique conversion for instruction ({0}), but "
133  "got conflicting {1} and {2} conversions",
134  *intrinsicIt, iface.getDialect()->getNamespace(),
135  instructionToDialect.lookup(*intrinsicIt)
136  ->getDialect()
137  ->getNamespace()));
138  }
139  // Add a mapping for all supported intrinsic identifiers.
140  for (unsigned id : iface.getSupportedIntrinsics())
141  intrinsicToDialect[id] = iface.getDialect();
142  // Add a mapping for all supported instruction identifiers.
143  for (unsigned id : iface.getSupportedInstructions())
144  instructionToDialect[id] = &iface;
145  // Add a mapping for all supported metadata kinds.
146  for (unsigned kind : iface.getSupportedMetadata(llvmContext))
147  metadataToDialect[kind].push_back(iface.getDialect());
148  }
149 
150  return success();
151  }
152 
153  /// Converts the LLVM intrinsic to an MLIR operation if a conversion exists.
154  /// Returns failure otherwise.
155  LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
156  LLVM::ModuleImport &moduleImport) const;
157 
158  /// Returns true if the given LLVM IR intrinsic is convertible to an MLIR
159  /// operation.
161  return intrinsicToDialect.count(id);
162  }
163 
164  /// Converts the LLVM instruction to an MLIR operation if a conversion exists.
165  /// Returns failure otherwise.
166  LogicalResult convertInstruction(OpBuilder &builder, llvm::Instruction *inst,
167  ArrayRef<llvm::Value *> llvmOperands,
168  LLVM::ModuleImport &moduleImport) const {
169  // Lookup the dialect interface for the given instruction.
170  const LLVMImportDialectInterface *iface =
171  instructionToDialect.lookup(inst->getOpcode());
172  if (!iface)
173  return failure();
174 
175  return iface->convertInstruction(builder, inst, llvmOperands, moduleImport);
176  }
177 
178  /// Returns true if the given LLVM IR instruction is convertible to an MLIR
179  /// operation.
180  bool isConvertibleInstruction(unsigned id) {
181  return instructionToDialect.count(id);
182  }
183 
184  /// Attaches the given LLVM metadata to the imported operation if a conversion
185  /// to one or more MLIR dialect attributes exists and succeeds. Returns
186  /// success if at least one of the conversions is successful and failure if
187  /// all of them fail.
188  LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind,
189  llvm::MDNode *node, Operation *op,
190  LLVM::ModuleImport &moduleImport) const {
191  // Lookup the dialect interfaces for the given metadata.
192  auto it = metadataToDialect.find(kind);
193  if (it == metadataToDialect.end())
194  return failure();
195 
196  // Dispatch the conversion to the dialect interfaces.
197  bool isSuccess = false;
198  for (Dialect *dialect : it->getSecond()) {
199  const LLVMImportDialectInterface *iface = getInterfaceFor(dialect);
200  assert(iface && "expected to find a dialect interface");
201  if (succeeded(
202  iface->setMetadataAttrs(builder, kind, node, op, moduleImport)))
203  isSuccess = true;
204  }
205 
206  // Returns failure if all conversions fail.
207  return success(isSuccess);
208  }
209 
210  /// Returns true if the given LLVM IR metadata is convertible to an MLIR
211  /// attribute.
212  bool isConvertibleMetadata(unsigned kind) {
213  return metadataToDialect.count(kind);
214  }
215 
216 private:
217  /// Generate llvm.call_intrinsic when no supporting dialect available.
218  static LogicalResult
219  convertUnregisteredIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
220  LLVM::ModuleImport &moduleImport);
221 
222  DenseMap<unsigned, Dialect *> intrinsicToDialect;
225 };
226 
227 } // namespace mlir
228 
229 #endif // MLIR_TARGET_LLVMIR_LLVMIMPORTINTERFACE_H
union mlir::linalg::@1196::ArityGroupAndKind::Kind kind
A collection of dialect interfaces within a context, for a given concrete interface type.
DialectInterfaceCollection< LLVMImportDialectInterface > Base
const LLVMImportDialectInterface * getInterfaceFor(Object *obj) const
Get the interface for a given object, or null if one is not registered.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:38
Base class for dialect interfaces used to import LLVM IR.
virtual LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst, LLVM::ModuleImport &moduleImport) const
Hook for derived dialect interfaces to implement the import of intrinsics into MLIR.
LLVMImportDialectInterface(Dialect *dialect)
virtual ArrayRef< unsigned > getSupportedIntrinsics() const
Hook for derived dialect interfaces to publish the supported intrinsics.
virtual ArrayRef< unsigned > getSupportedInstructions() const
Hook for derived dialect interfaces to publish the supported instructions.
virtual ArrayRef< unsigned > getSupportedMetadata(llvm::LLVMContext &ctx) const
Hook for derived dialect interfaces to publish the supported metadata kinds.
virtual LogicalResult convertInstruction(OpBuilder &builder, llvm::Instruction *inst, ArrayRef< llvm::Value * > llvmOperands, LLVM::ModuleImport &moduleImport) const
Hook for derived dialect interfaces to implement the import of instructions into MLIR.
virtual LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind, llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) const
Hook for derived dialect interfaces to implement the import of metadata into MLIR.
Interface collection for the import of LLVM IR that dispatches to a concrete dialect interface implem...
LogicalResult convertInstruction(OpBuilder &builder, llvm::Instruction *inst, ArrayRef< llvm::Value * > llvmOperands, LLVM::ModuleImport &moduleImport) const
Converts the LLVM instruction to an MLIR operation if a conversion exists.
LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst, LLVM::ModuleImport &moduleImport) const
Converts the LLVM intrinsic to an MLIR operation if a conversion exists.
LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind, llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) const
Attaches the given LLVM metadata to the imported operation if a conversion to one or more MLIR dialec...
bool isConvertibleMetadata(unsigned kind)
Returns true if the given LLVM IR metadata is convertible to an MLIR attribute.
LogicalResult initializeImport(llvm::LLVMContext &llvmContext)
Queries all registered dialect interfaces for the supported LLVM IR intrinsic and metadata kinds and ...
bool isConvertibleInstruction(unsigned id)
Returns true if the given LLVM IR instruction is convertible to an MLIR operation.
bool isConvertibleIntrinsic(llvm::Intrinsic::ID id)
Returns true if the given LLVM IR intrinsic is convertible to an MLIR operation.
Module import implementation class that provides methods to import globals and functions from an LLVM...
Definition: ModuleImport.h:47
This class helps build Operations.
Definition: Builders.h:205
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
The base class used for all derived interface types.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition: CallGraph.h:229
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...