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. `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> {
101public:
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.
160 bool isConvertibleIntrinsic(llvm::Intrinsic::ID id) {
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
216private:
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
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 > getSupportedMetadata(llvm::LLVMContext &ctx) const
Hook for derived dialect interfaces to publish the supported metadata kinds.
virtual ArrayRef< unsigned > getSupportedIntrinsics() const
Hook for derived dialect interfaces to publish the supported intrinsics.
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