MLIR 22.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
26namespace llvm {
27class IRBuilderBase;
28} // namespace llvm
29
30namespace mlir {
31namespace LLVM {
32class 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> {
43public:
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. The
88 /// `llvmContext` parameter is used to obtain identifiers for metadata kinds
89 /// that do not have a fixed static identifier. Since different LLVM contexts
90 /// can assign different identifiers to these non-static metadata kinds, the
91 /// function must recompute the list of supported metadata identifiers on each
92 /// call.
94 getSupportedMetadata(llvm::LLVMContext &llvmContext) const {
95 return {};
96 }
97};
98
99/// Interface collection for the import of LLVM IR that dispatches to a concrete
100/// dialect interface implementation. Queries the dialect interfaces to obtain a
101/// list of the supported LLVM IR constructs and then builds a mapping for the
102/// efficient dispatch.
104 : public DialectInterfaceCollection<LLVMImportDialectInterface> {
105public:
106 using Base::Base;
107
108 /// Queries all registered dialect interfaces for the supported LLVM IR
109 /// intrinsic and metadata kinds and builds the dispatch tables for the
110 /// conversion. Returns failure if multiple dialect interfaces translate the
111 /// same LLVM IR intrinsic.
112 LogicalResult initializeImport(llvm::LLVMContext &llvmContext) {
113 for (const LLVMImportDialectInterface &iface : *this) {
114 // Verify the supported intrinsics have not been mapped before.
115 const auto *intrinsicIt =
116 llvm::find_if(iface.getSupportedIntrinsics(), [&](unsigned id) {
117 return intrinsicToDialect.count(id);
118 });
119 if (intrinsicIt != iface.getSupportedIntrinsics().end()) {
120 return emitError(
121 UnknownLoc::get(iface.getContext()),
122 llvm::formatv(
123 "expected unique conversion for intrinsic ({0}), but "
124 "got conflicting {1} and {2} conversions",
125 *intrinsicIt, iface.getDialect()->getNamespace(),
126 intrinsicToDialect.lookup(*intrinsicIt)->getNamespace()));
127 }
128 const auto *instructionIt =
129 llvm::find_if(iface.getSupportedInstructions(), [&](unsigned id) {
130 return instructionToDialect.count(id);
131 });
132 if (instructionIt != iface.getSupportedInstructions().end()) {
133 return emitError(
134 UnknownLoc::get(iface.getContext()),
135 llvm::formatv(
136 "expected unique conversion for instruction ({0}), but "
137 "got conflicting {1} and {2} conversions",
138 *intrinsicIt, iface.getDialect()->getNamespace(),
139 instructionToDialect.lookup(*intrinsicIt)
140 ->getDialect()
141 ->getNamespace()));
142 }
143 // Add a mapping for all supported intrinsic identifiers.
144 for (unsigned id : iface.getSupportedIntrinsics())
145 intrinsicToDialect[id] = iface.getDialect();
146 // Add a mapping for all supported instruction identifiers.
147 for (unsigned id : iface.getSupportedInstructions())
148 instructionToDialect[id] = &iface;
149 // Add a mapping for all supported metadata kinds.
150 for (unsigned kind : iface.getSupportedMetadata(llvmContext))
151 metadataToDialect[kind].push_back(iface.getDialect());
152 }
153
154 return success();
155 }
156
157 /// Converts the LLVM intrinsic to an MLIR operation if a conversion exists.
158 /// Returns failure otherwise.
159 LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
160 LLVM::ModuleImport &moduleImport) const;
161
162 /// Returns true if the given LLVM IR intrinsic is convertible to an MLIR
163 /// operation.
164 bool isConvertibleIntrinsic(llvm::Intrinsic::ID id) {
165 return intrinsicToDialect.count(id);
166 }
167
168 /// Converts the LLVM instruction to an MLIR operation if a conversion exists.
169 /// Returns failure otherwise.
170 LogicalResult convertInstruction(OpBuilder &builder, llvm::Instruction *inst,
171 ArrayRef<llvm::Value *> llvmOperands,
172 LLVM::ModuleImport &moduleImport) const {
173 // Lookup the dialect interface for the given instruction.
174 const LLVMImportDialectInterface *iface =
175 instructionToDialect.lookup(inst->getOpcode());
176 if (!iface)
177 return failure();
178
179 return iface->convertInstruction(builder, inst, llvmOperands, moduleImport);
180 }
181
182 /// Returns true if the given LLVM IR instruction is convertible to an MLIR
183 /// operation.
184 bool isConvertibleInstruction(unsigned id) {
185 return instructionToDialect.count(id);
186 }
187
188 /// Attaches the given LLVM metadata to the imported operation if a conversion
189 /// to one or more MLIR dialect attributes exists and succeeds. Returns
190 /// success if at least one of the conversions is successful and failure if
191 /// all of them fail.
192 LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind,
193 llvm::MDNode *node, Operation *op,
194 LLVM::ModuleImport &moduleImport) const {
195 // Lookup the dialect interfaces for the given metadata.
196 auto it = metadataToDialect.find(kind);
197 if (it == metadataToDialect.end())
198 return failure();
199
200 // Dispatch the conversion to the dialect interfaces.
201 bool isSuccess = false;
202 for (Dialect *dialect : it->getSecond()) {
203 const LLVMImportDialectInterface *iface = getInterfaceFor(dialect);
204 assert(iface && "expected to find a dialect interface");
205 if (succeeded(
206 iface->setMetadataAttrs(builder, kind, node, op, moduleImport)))
207 isSuccess = true;
208 }
209
210 // Returns failure if all conversions fail.
211 return success(isSuccess);
212 }
213
214 /// Returns true if the given LLVM IR metadata is convertible to an MLIR
215 /// attribute.
216 bool isConvertibleMetadata(unsigned kind) {
217 return metadataToDialect.count(kind);
218 }
219
220private:
221 /// Generate llvm.call_intrinsic when no supporting dialect available.
222 static LogicalResult
223 convertUnregisteredIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
224 LLVM::ModuleImport &moduleImport);
225
226 DenseMap<unsigned, Dialect *> intrinsicToDialect;
229};
230
231} // namespace mlir
232
233#endif // MLIR_TARGET_LLVMIR_LLVMIMPORTINTERFACE_H
return success()
DialectInterfaceCollection< LLVMImportDialectInterface > Base
const LLVMImportDialectInterface * getInterfaceFor(Object *obj) const
MLIRContext * getContext() const
Return the context that holds the parent dialect of this interface.
Definition Dialect.cpp:117
Dialect * getDialect() const
Return the dialect that this interface represents.
detail::DialectInterfaceBase< ConcreteType, DialectInterface > Base
The base class used for all derived interface types.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition Dialect.h:38
StringRef getNamespace() const
Definition Dialect.h:54
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.
virtual ArrayRef< unsigned > getSupportedIntrinsics() const
Hook for derived dialect interfaces to publish the supported intrinsics.
virtual SmallVector< unsigned > getSupportedMetadata(llvm::LLVMContext &llvmContext) 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.
virtual ArrayRef< unsigned > getSupportedInstructions() const
Hook for derived dialect interfaces to publish the supported instructions.
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...
This class helps build Operations.
Definition Builders.h:207
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
DialectInterfaceBase< ConcreteType, DialectInterface > Base
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.
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:126