@@ -52,6 +52,15 @@ class LLVMImportDialectInterface
52
52
return failure ();
53
53
}
54
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
+
55
64
// / Hook for derived dialect interfaces to implement the import of metadata
56
65
// / into MLIR. Attaches the converted metadata kind and node to the provided
57
66
// / operation.
@@ -66,6 +75,14 @@ class LLVMImportDialectInterface
66
75
// / returns the list of supported intrinsic identifiers.
67
76
virtual ArrayRef<unsigned > getSupportedIntrinsics () const { return {}; }
68
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
+
69
86
// / Hook for derived dialect interfaces to publish the supported metadata
70
87
// / kinds. As every metadata kind has a unique integer identifier, the
71
88
// / function returns the list of supported metadata identifiers.
@@ -88,21 +105,40 @@ class LLVMImportInterface
88
105
LogicalResult initializeImport () {
89
106
for (const LLVMImportDialectInterface &iface : *this ) {
90
107
// Verify the supported intrinsics have not been mapped before.
91
- const auto *it =
108
+ const auto *intrinsicIt =
92
109
llvm::find_if (iface.getSupportedIntrinsics (), [&](unsigned id) {
93
110
return intrinsicToDialect.count (id);
94
111
});
95
- if (it != iface.getSupportedIntrinsics ().end ()) {
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 ()) {
96
126
return emitError (
97
127
UnknownLoc::get (iface.getContext ()),
98
- llvm::formatv (" expected unique conversion for intrinsic ({0}), but "
99
- " got conflicting {1} and {2} conversions" ,
100
- *it, iface.getDialect ()->getNamespace (),
101
- intrinsicToDialect.lookup (*it)->getNamespace ()));
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 ()));
102
135
}
103
136
// Add a mapping for all supported intrinsic identifiers.
104
137
for (unsigned id : iface.getSupportedIntrinsics ())
105
138
intrinsicToDialect[id] = iface.getDialect ();
139
+ // Add a mapping for all supported instruction identifiers.
140
+ for (unsigned id : iface.getSupportedInstructions ())
141
+ instructionToDialect[id] = &iface;
106
142
// Add a mapping for all supported metadata kinds.
107
143
for (unsigned kind : iface.getSupportedMetadata ())
108
144
metadataToDialect[kind].push_back (iface.getDialect ());
@@ -132,6 +168,26 @@ class LLVMImportInterface
132
168
return intrinsicToDialect.count (id);
133
169
}
134
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
+
135
191
// / Attaches the given LLVM metadata to the imported operation if a conversion
136
192
// / to one or more MLIR dialect attributes exists and succeeds. Returns
137
193
// / success if at least one of the conversions is successful and failure if
@@ -166,6 +222,7 @@ class LLVMImportInterface
166
222
167
223
private:
168
224
DenseMap<unsigned , Dialect *> intrinsicToDialect;
225
+ DenseMap<unsigned , const LLVMImportDialectInterface *> instructionToDialect;
169
226
DenseMap<unsigned , SmallVector<Dialect *, 1 >> metadataToDialect;
170
227
};
171
228
0 commit comments