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