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.
88  virtual ArrayRef<unsigned> getSupportedMetadata() const { return {}; }
89 };
90 
91 /// Interface collection for the import of LLVM IR that dispatches to a concrete
92 /// dialect interface implementation. Queries the dialect interfaces to obtain a
93 /// list of the supported LLVM IR constructs and then builds a mapping for the
94 /// efficient dispatch.
96  : public DialectInterfaceCollection<LLVMImportDialectInterface> {
97 public:
98  using Base::Base;
99 
100  /// Queries all registered dialect interfaces for the supported LLVM IR
101  /// intrinsic and metadata kinds and builds the dispatch tables for the
102  /// conversion. Returns failure if multiple dialect interfaces translate the
103  /// same LLVM IR intrinsic.
104  LogicalResult initializeImport() {
105  for (const LLVMImportDialectInterface &iface : *this) {
106  // Verify the supported intrinsics have not been mapped before.
107  const auto *intrinsicIt =
108  llvm::find_if(iface.getSupportedIntrinsics(), [&](unsigned id) {
109  return intrinsicToDialect.count(id);
110  });
111  if (intrinsicIt != iface.getSupportedIntrinsics().end()) {
112  return emitError(
113  UnknownLoc::get(iface.getContext()),
114  llvm::formatv(
115  "expected unique conversion for intrinsic ({0}), but "
116  "got conflicting {1} and {2} conversions",
117  *intrinsicIt, iface.getDialect()->getNamespace(),
118  intrinsicToDialect.lookup(*intrinsicIt)->getNamespace()));
119  }
120  const auto *instructionIt =
121  llvm::find_if(iface.getSupportedInstructions(), [&](unsigned id) {
122  return instructionToDialect.count(id);
123  });
124  if (instructionIt != iface.getSupportedInstructions().end()) {
125  return emitError(
126  UnknownLoc::get(iface.getContext()),
127  llvm::formatv(
128  "expected unique conversion for instruction ({0}), but "
129  "got conflicting {1} and {2} conversions",
130  *intrinsicIt, iface.getDialect()->getNamespace(),
131  instructionToDialect.lookup(*intrinsicIt)
132  ->getDialect()
133  ->getNamespace()));
134  }
135  // Add a mapping for all supported intrinsic identifiers.
136  for (unsigned id : iface.getSupportedIntrinsics())
137  intrinsicToDialect[id] = iface.getDialect();
138  // Add a mapping for all supported instruction identifiers.
139  for (unsigned id : iface.getSupportedInstructions())
140  instructionToDialect[id] = &iface;
141  // Add a mapping for all supported metadata kinds.
142  for (unsigned kind : iface.getSupportedMetadata())
143  metadataToDialect[kind].push_back(iface.getDialect());
144  }
145 
146  return success();
147  }
148 
149  /// Converts the LLVM intrinsic to an MLIR operation if a conversion exists.
150  /// Returns failure otherwise.
151  LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
152  LLVM::ModuleImport &moduleImport) const {
153  // Lookup the dialect interface for the given intrinsic.
154  Dialect *dialect = intrinsicToDialect.lookup(inst->getIntrinsicID());
155  if (!dialect)
156  return failure();
157 
158  // Dispatch the conversion to the dialect interface.
159  const LLVMImportDialectInterface *iface = getInterfaceFor(dialect);
160  assert(iface && "expected to find a dialect interface");
161  return iface->convertIntrinsic(builder, inst, moduleImport);
162  }
163 
164  /// Returns true if the given LLVM IR intrinsic is convertible to an MLIR
165  /// operation.
167  return intrinsicToDialect.count(id);
168  }
169 
170  /// Converts the LLVM instruction to an MLIR operation if a conversion exists.
171  /// Returns failure otherwise.
172  LogicalResult convertInstruction(OpBuilder &builder, llvm::Instruction *inst,
173  ArrayRef<llvm::Value *> llvmOperands,
174  LLVM::ModuleImport &moduleImport) const {
175  // Lookup the dialect interface for the given instruction.
176  const LLVMImportDialectInterface *iface =
177  instructionToDialect.lookup(inst->getOpcode());
178  if (!iface)
179  return failure();
180 
181  return iface->convertInstruction(builder, inst, llvmOperands, moduleImport);
182  }
183 
184  /// Returns true if the given LLVM IR instruction is convertible to an MLIR
185  /// operation.
186  bool isConvertibleInstruction(unsigned id) {
187  return instructionToDialect.count(id);
188  }
189 
190  /// Attaches the given LLVM metadata to the imported operation if a conversion
191  /// to one or more MLIR dialect attributes exists and succeeds. Returns
192  /// success if at least one of the conversions is successful and failure if
193  /// all of them fail.
194  LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind,
195  llvm::MDNode *node, Operation *op,
196  LLVM::ModuleImport &moduleImport) const {
197  // Lookup the dialect interfaces for the given metadata.
198  auto it = metadataToDialect.find(kind);
199  if (it == metadataToDialect.end())
200  return failure();
201 
202  // Dispatch the conversion to the dialect interfaces.
203  bool isSuccess = false;
204  for (Dialect *dialect : it->getSecond()) {
205  const LLVMImportDialectInterface *iface = getInterfaceFor(dialect);
206  assert(iface && "expected to find a dialect interface");
207  if (succeeded(
208  iface->setMetadataAttrs(builder, kind, node, op, moduleImport)))
209  isSuccess = true;
210  }
211 
212  // Returns failure if all conversions fail.
213  return success(isSuccess);
214  }
215 
216  /// Returns true if the given LLVM IR metadata is convertible to an MLIR
217  /// attribute.
218  bool isConvertibleMetadata(unsigned kind) {
219  return metadataToDialect.count(kind);
220  }
221 
222 private:
223  DenseMap<unsigned, Dialect *> intrinsicToDialect;
226 };
227 
228 } // namespace mlir
229 
230 #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 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 ArrayRef< unsigned > getSupportedMetadata() const
Hook for derived dialect interfaces to publish the supported metadata kinds.
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 initializeImport()
Queries all registered dialect interfaces for the supported LLVM IR intrinsic and metadata kinds and ...
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.
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:210
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
The base class used for all derived interface types.
Include the generated interface declarations.
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...