MLIR  20.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  // Lookup the dialect interface for the given intrinsic.
158  Dialect *dialect = intrinsicToDialect.lookup(inst->getIntrinsicID());
159  if (!dialect)
160  return failure();
161 
162  // Dispatch the conversion to the dialect interface.
163  const LLVMImportDialectInterface *iface = getInterfaceFor(dialect);
164  assert(iface && "expected to find a dialect interface");
165  return iface->convertIntrinsic(builder, inst, moduleImport);
166  }
167 
168  /// Returns true if the given LLVM IR intrinsic is convertible to an MLIR
169  /// operation.
171  return intrinsicToDialect.count(id);
172  }
173 
174  /// Converts the LLVM instruction to an MLIR operation if a conversion exists.
175  /// Returns failure otherwise.
176  LogicalResult convertInstruction(OpBuilder &builder, llvm::Instruction *inst,
177  ArrayRef<llvm::Value *> llvmOperands,
178  LLVM::ModuleImport &moduleImport) const {
179  // Lookup the dialect interface for the given instruction.
180  const LLVMImportDialectInterface *iface =
181  instructionToDialect.lookup(inst->getOpcode());
182  if (!iface)
183  return failure();
184 
185  return iface->convertInstruction(builder, inst, llvmOperands, moduleImport);
186  }
187 
188  /// Returns true if the given LLVM IR instruction is convertible to an MLIR
189  /// operation.
190  bool isConvertibleInstruction(unsigned id) {
191  return instructionToDialect.count(id);
192  }
193 
194  /// Attaches the given LLVM metadata to the imported operation if a conversion
195  /// to one or more MLIR dialect attributes exists and succeeds. Returns
196  /// success if at least one of the conversions is successful and failure if
197  /// all of them fail.
198  LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind,
199  llvm::MDNode *node, Operation *op,
200  LLVM::ModuleImport &moduleImport) const {
201  // Lookup the dialect interfaces for the given metadata.
202  auto it = metadataToDialect.find(kind);
203  if (it == metadataToDialect.end())
204  return failure();
205 
206  // Dispatch the conversion to the dialect interfaces.
207  bool isSuccess = false;
208  for (Dialect *dialect : it->getSecond()) {
209  const LLVMImportDialectInterface *iface = getInterfaceFor(dialect);
210  assert(iface && "expected to find a dialect interface");
211  if (succeeded(
212  iface->setMetadataAttrs(builder, kind, node, op, moduleImport)))
213  isSuccess = true;
214  }
215 
216  // Returns failure if all conversions fail.
217  return success(isSuccess);
218  }
219 
220  /// Returns true if the given LLVM IR metadata is convertible to an MLIR
221  /// attribute.
222  bool isConvertibleMetadata(unsigned kind) {
223  return metadataToDialect.count(kind);
224  }
225 
226 private:
227  DenseMap<unsigned, Dialect *> intrinsicToDialect;
230 };
231 
232 } // namespace mlir
233 
234 #endif // MLIR_TARGET_LLVMIR_LLVMIMPORTINTERFACE_H
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:215
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...