19#include "mlir/Config/mlir-config.h"
20#include "nanobind/nanobind.h"
24using namespace nb::literals;
29class PyPatternRewriter {
31 PyPatternRewriter(MlirPatternRewriter rewriter)
35 PyInsertionPoint getInsertionPoint()
const {
39 if (mlirOperationIsNull(op)) {
42 return PyInsertionPoint(PyBlock(parent, block));
48 void replaceOp(MlirOperation op, MlirOperation newOp) {
52 void replaceOp(MlirOperation op,
const std::vector<MlirValue> &values) {
59 MlirRewriterBase base;
63#if MLIR_ENABLE_PDL_IN_PATTERNMATCH
64static nb::object objectFromPDLValue(MlirPDLValue value) {
65 if (MlirValue v = mlirPDLValueAsValue(value); !mlirValueIsNull(v))
67 if (MlirOperation v = mlirPDLValueAsOperation(value); !mlirOperationIsNull(v))
69 if (MlirAttribute v = mlirPDLValueAsAttribute(value); !mlirAttributeIsNull(v))
74 throw std::runtime_error(
"unsupported PDL value type");
77static std::vector<nb::object> objectsFromPDLValues(
size_t nValues,
78 MlirPDLValue *values) {
79 std::vector<nb::object> args;
80 args.reserve(nValues);
81 for (
size_t i = 0; i < nValues; ++i)
82 args.push_back(objectFromPDLValue(values[i]));
99class PyPDLPatternModule {
101 PyPDLPatternModule(MlirPDLPatternModule module) : module(module) {}
102 PyPDLPatternModule(PyPDLPatternModule &&other) noexcept
103 : module(other.module) {
104 other.module.ptr =
nullptr;
106 ~PyPDLPatternModule() {
107 if (module.ptr !=
nullptr)
108 mlirPDLPatternModuleDestroy(module);
110 MlirPDLPatternModule
get() {
return module; }
112 void registerRewriteFunction(
const std::string &name,
113 const nb::callable &fn) {
114 mlirPDLPatternModuleRegisterRewriteFunction(
116 [](MlirPatternRewriter rewriter, MlirPDLResultList results,
117 size_t nValues, MlirPDLValue *values,
119 nb::handle f = nb::handle(static_cast<PyObject *>(userData));
120 return logicalResultFromObject(
121 f(PyPatternRewriter(rewriter), results,
122 objectsFromPDLValues(nValues, values)));
127 void registerConstraintFunction(
const std::string &name,
128 const nb::callable &fn) {
129 mlirPDLPatternModuleRegisterConstraintFunction(
131 [](MlirPatternRewriter rewriter, MlirPDLResultList results,
132 size_t nValues, MlirPDLValue *values,
134 nb::handle f = nb::handle(static_cast<PyObject *>(userData));
135 return logicalResultFromObject(
136 f(PyPatternRewriter(rewriter), results,
137 objectsFromPDLValues(nValues, values)));
143 MlirPDLPatternModule module;
148class PyFrozenRewritePatternSet {
150 PyFrozenRewritePatternSet(MlirFrozenRewritePatternSet set) : set(set) {}
151 PyFrozenRewritePatternSet(PyFrozenRewritePatternSet &&other) noexcept
153 other.set.ptr =
nullptr;
155 ~PyFrozenRewritePatternSet() {
156 if (set.ptr !=
nullptr)
159 MlirFrozenRewritePatternSet
get() {
return set; }
161 nb::object getCapsule() {
162 return nb::steal<nb::object>(
166 static nb::object createFromCapsule(
const nb::object &capsule) {
167 MlirFrozenRewritePatternSet rawPm =
169 if (rawPm.ptr ==
nullptr)
170 throw nb::python_error();
171 return nb::cast(PyFrozenRewritePatternSet(rawPm), nb::rv_policy::move);
175 MlirFrozenRewritePatternSet set;
178class PyRewritePatternSet {
180 PyRewritePatternSet(MlirContext ctx)
182 ~PyRewritePatternSet() {
188 const nb::callable &matchAndRewrite) {
189 MlirRewritePatternCallbacks callbacks;
190 callbacks.
construct = [](
void *userData) {
191 nb::handle(
static_cast<PyObject *
>(userData)).inc_ref();
193 callbacks.
destruct = [](
void *userData) {
194 nb::handle(
static_cast<PyObject *
>(userData)).dec_ref();
197 MlirPatternRewriter rewriter,
199 nb::handle f(
static_cast<PyObject *
>(userData));
205 nb::object res = f(opView, PyPatternRewriter(rewriter));
206 return logicalResultFromObject(res);
209 rootName, benefit, ctx, callbacks, matchAndRewrite.ptr(),
215 PyFrozenRewritePatternSet freeze() {
216 MlirRewritePatternSet s = set;
222 MlirRewritePatternSet set;
227class PyGreedyRewriteDriverConfig {
229 PyGreedyRewriteDriverConfig()
231 PyGreedyRewriteDriverConfig(PyGreedyRewriteDriverConfig &&other) noexcept
233 other.config.ptr =
nullptr;
235 ~PyGreedyRewriteDriverConfig() {
236 if (
config.ptr !=
nullptr)
239 MlirGreedyRewriteDriverConfig
get() {
return config; }
241 void setMaxIterations(int64_t maxIterations) {
245 void setMaxNumRewrites(int64_t maxNumRewrites) {
249 void setUseTopDownTraversal(
bool useTopDownTraversal) {
251 useTopDownTraversal);
254 void enableFolding(
bool enable) {
266 void enableConstantCSE(
bool enable) {
270 int64_t getMaxIterations() {
274 int64_t getMaxNumRewrites() {
278 bool getUseTopDownTraversal() {
282 bool isFoldingEnabled() {
294 bool isConstantCSEEnabled() {
299 MlirGreedyRewriteDriverConfig
config;
307 nb::enum_<MlirGreedyRewriteStrictness>(m,
"GreedyRewriteStrictness")
309 .value(
"EXISTING_AND_NEW_OPS",
313 nb::enum_<MlirGreedySimplifyRegionLevel>(m,
"GreedySimplifyRegionLevel")
322 class_<PyPatternRewriter>(m,
"PatternRewriter")
323 .def_prop_ro(
"ip", &PyPatternRewriter::getInsertionPoint,
324 "The current insertion point of the PatternRewriter.")
327 [](PyPatternRewriter &self, MlirOperation op,
328 MlirOperation newOp) { self.replaceOp(op, newOp); },
329 "Replace an operation with a new operation.", nb::arg(
"op"),
337 [](PyPatternRewriter &self, MlirOperation op,
338 const std::vector<MlirValue> &values) {
339 self.replaceOp(op, values);
341 "Replace an operation with a list of values.", nb::arg(
"op"),
347 .def(
"erase_op", &PyPatternRewriter::eraseOp,
"Erase an operation.",
357 nb::class_<PyRewritePatternSet>(m,
"RewritePatternSet")
361 new (&self) PyRewritePatternSet(context.
get()->
get());
363 "context"_a = nb::none())
366 [](PyRewritePatternSet &self, nb::handle root,
const nb::callable &fn,
369 if (root.is_type()) {
370 opName = nb::cast<std::string>(root.attr(
"OPERATION_NAME"));
371 }
else if (nb::isinstance<nb::str>(root)) {
372 opName = nb::cast<std::string>(root);
374 throw nb::type_error(
375 "the root argument must be a type or a string");
380 "root"_a,
"fn"_a,
"benefit"_a = 1,
382 nb::sig(
"def add(self, root: type | str, fn: typing.Callable[[" MAKE_MLIR_PYTHON_QUALNAME(
"ir.Operation")
", PatternRewriter], typing.Any], benefit: int = 1) -> None"),
385 Add a new rewrite pattern on the specified root operation, using the provided callable
386 for matching and rewriting, and assign it the given benefit.
389 root: The root operation to which this pattern applies.
390 This may be either an OpView subclass (e.g., ``arith.AddIOp``) or
391 an operation name string (e.g., ``"arith.addi"``).
392 fn: The callable to use for matching and rewriting,
393 which takes an operation and a pattern rewriter as arguments.
394 The match is considered successful iff the callable returns
395 a value where ``bool(value)`` is ``False`` (e.g. ``None``).
396 If possible, the operation is cast to its corresponding OpView subclass
397 before being passed to the callable.
398 benefit: The benefit of the pattern, defaulting to 1.)")
399 .def("freeze", &PyRewritePatternSet::freeze,
400 "Freeze the pattern set into a frozen one.");
405#if MLIR_ENABLE_PDL_IN_PATTERNMATCH
406 nb::class_<MlirPDLResultList>(m,
"PDLResultList")
409 [](MlirPDLResultList results,
const PyValue &value) {
410 mlirPDLResultListPushBackValue(results, value);
418 [](MlirPDLResultList results,
const PyOperation &op) {
419 mlirPDLResultListPushBackOperation(results, op);
427 [](MlirPDLResultList results,
const PyType &type) {
428 mlirPDLResultListPushBackType(results, type);
436 [](MlirPDLResultList results,
const PyAttribute &attr) {
437 mlirPDLResultListPushBackAttribute(results, attr);
443 nb::class_<PyPDLPatternModule>(m,
"PDLModule")
446 [](PyPDLPatternModule &self, MlirModule module) {
448 PyPDLPatternModule(mlirPDLPatternModuleFromModule(module));
453 "module"_a,
"Create a PDL module from the given module.")
456 [](PyPDLPatternModule &self,
PyModule &module) {
457 new (&self) PyPDLPatternModule(
458 mlirPDLPatternModuleFromModule(module.
get()));
463 "module"_a,
"Create a PDL module from the given module.")
466 [](PyPDLPatternModule &self) {
468 mlirRewritePatternSetFromPDLPatternModule(self.get())));
470 nb::keep_alive<0, 1>())
472 "register_rewrite_function",
473 [](PyPDLPatternModule &self,
const std::string &name,
474 const nb::callable &fn) {
475 self.registerRewriteFunction(name, fn);
477 nb::keep_alive<1, 3>())
479 "register_constraint_function",
480 [](PyPDLPatternModule &self,
const std::string &name,
481 const nb::callable &fn) {
482 self.registerConstraintFunction(name, fn);
484 nb::keep_alive<1, 3>());
487 nb::class_<PyGreedyRewriteDriverConfig>(m,
"GreedyRewriteDriverConfig")
488 .def(nb::init<>(),
"Create a greedy rewrite driver config with defaults")
489 .def_prop_rw(
"max_iterations",
490 &PyGreedyRewriteDriverConfig::getMaxIterations,
491 &PyGreedyRewriteDriverConfig::setMaxIterations,
492 "Maximum number of iterations")
493 .def_prop_rw(
"max_num_rewrites",
494 &PyGreedyRewriteDriverConfig::getMaxNumRewrites,
495 &PyGreedyRewriteDriverConfig::setMaxNumRewrites,
496 "Maximum number of rewrites per iteration")
497 .def_prop_rw(
"use_top_down_traversal",
498 &PyGreedyRewriteDriverConfig::getUseTopDownTraversal,
499 &PyGreedyRewriteDriverConfig::setUseTopDownTraversal,
500 "Whether to use top-down traversal")
501 .def_prop_rw(
"enable_folding",
502 &PyGreedyRewriteDriverConfig::isFoldingEnabled,
503 &PyGreedyRewriteDriverConfig::enableFolding,
504 "Enable or disable folding")
505 .def_prop_rw(
"strictness", &PyGreedyRewriteDriverConfig::getStrictness,
506 &PyGreedyRewriteDriverConfig::setStrictness,
507 "Rewrite strictness level")
508 .def_prop_rw(
"region_simplification_level",
509 &PyGreedyRewriteDriverConfig::getRegionSimplificationLevel,
510 &PyGreedyRewriteDriverConfig::setRegionSimplificationLevel,
511 "Region simplification level")
512 .def_prop_rw(
"enable_constant_cse",
513 &PyGreedyRewriteDriverConfig::isConstantCSEEnabled,
514 &PyGreedyRewriteDriverConfig::enableConstantCSE,
515 "Enable or disable constant CSE");
517 nb::class_<PyFrozenRewritePatternSet>(m,
"FrozenRewritePatternSet")
519 &PyFrozenRewritePatternSet::getCapsule)
521 &PyFrozenRewritePatternSet::createFromCapsule);
523 "apply_patterns_and_fold_greedily",
524 [](
PyModule &module, PyFrozenRewritePatternSet &set) {
528 throw std::runtime_error(
"pattern application failed to converge");
532 nb::sig(
"def apply_patterns_and_fold_greedily(module: " MAKE_MLIR_PYTHON_QUALNAME(
"ir.Module")
", set: FrozenRewritePatternSet) -> None"),
534 "Applys the given patterns to the given module greedily while folding "
537 "apply_patterns_and_fold_greedily",
538 [](
PyModule &module, MlirFrozenRewritePatternSet set) {
542 throw std::runtime_error(
543 "pattern application failed to converge");
547 nb::sig(
"def apply_patterns_and_fold_greedily(module: " MAKE_MLIR_PYTHON_QUALNAME(
"ir.Module")
", set: FrozenRewritePatternSet) -> None"),
549 "Applys the given patterns to the given module greedily while "
553 "apply_patterns_and_fold_greedily",
559 throw std::runtime_error(
560 "pattern application failed to converge");
564 nb::sig(
"def apply_patterns_and_fold_greedily(op: " MAKE_MLIR_PYTHON_QUALNAME(
"ir._OperationBase")
", set: FrozenRewritePatternSet) -> None"),
566 "Applys the given patterns to the given op greedily while folding "
569 "apply_patterns_and_fold_greedily",
574 throw std::runtime_error(
575 "pattern application failed to converge");
579 nb::sig(
"def apply_patterns_and_fold_greedily(op: " MAKE_MLIR_PYTHON_QUALNAME(
"ir._OperationBase")
", set: FrozenRewritePatternSet) -> None"),
581 "Applys the given patterns to the given op greedily while folding "
584 "walk_and_apply_patterns",
590 nb::sig(
"def walk_and_apply_patterns(op: " MAKE_MLIR_PYTHON_QUALNAME(
"ir._OperationBase")
", set: FrozenRewritePatternSet) -> None"),
592 "Applies the given patterns to the given op by a fast walk-based "
MlirContext mlirOperationGetContext(MlirOperation op)
static MlirFrozenRewritePatternSet mlirPythonCapsuleToFrozenRewritePatternSet(PyObject *capsule)
Extracts an MlirFrozenRewritePatternSet from a capsule as produced from mlirPythonFrozenRewritePatter...
#define MLIR_PYTHON_CAPI_PTR_ATTR
Attribute on MLIR Python objects that expose their C-API pointer.
#define MLIR_PYTHON_CAPI_FACTORY_ATTR
Attribute on MLIR Python objects that exposes a factory function for constructing the corresponding P...
#define MAKE_MLIR_PYTHON_QUALNAME(local)
static PyObject * mlirPythonFrozenRewritePatternSetToCapsule(MlirFrozenRewritePatternSet pm)
Creates a capsule object encapsulating the raw C-API MlirFrozenRewritePatternSet.
Used in function arguments when None should resolve to the current context manager set instance.
ReferrentTy * get() const
Wrapper around the generic MlirAttribute.
MlirContext get()
Accesses the underlying MlirContext.
static PyMlirContextRef forContext(MlirContext context)
Returns a context reference for the singleton PyMlirContext wrapper for the given context.
MlirModule get()
Gets the backing MlirModule.
Base class for PyOperation and PyOpView which exposes the primary, user visible methods for manipulat...
virtual PyOperation & getOperation()=0
Each must provide access to the raw Operation.
static PyOperationRef forOperation(PyMlirContextRef contextRef, MlirOperation operation, nanobind::object parentKeepAlive=nanobind::object())
Returns a PyOperation for the given MlirOperation, optionally associating it with a parentKeepAlive.
nanobind::object createOpView()
Creates an OpView suitable for this operation.
Wrapper around the generic MlirType.
Wrapper around the generic MlirValue.
MLIR_CAPI_EXPORTED void mlirRewriterBaseReplaceOpWithValues(MlirRewriterBase rewriter, MlirOperation op, intptr_t nValues, MlirValue const *values)
Replace the results of the given (original) operation with the specified list of values (replacements...
MLIR_CAPI_EXPORTED void mlirGreedyRewriteDriverConfigEnableConstantCSE(MlirGreedyRewriteDriverConfig config, bool enable)
Enables or disables constant CSE.
MLIR_CAPI_EXPORTED MlirOperation mlirRewriterBaseGetOperationAfterInsertion(MlirRewriterBase rewriter)
Returns the operation right after the current insertion point of the rewriter.
MLIR_CAPI_EXPORTED MlirGreedySimplifyRegionLevel mlirGreedyRewriteDriverConfigGetRegionSimplificationLevel(MlirGreedyRewriteDriverConfig config)
Gets the region simplification level.
MLIR_CAPI_EXPORTED bool mlirGreedyRewriteDriverConfigIsFoldingEnabled(MlirGreedyRewriteDriverConfig config)
Gets whether folding is enabled during greedy rewriting.
MLIR_CAPI_EXPORTED MlirGreedyRewriteDriverConfig mlirGreedyRewriteDriverConfigCreate(void)
GreedyRewriteDriverConfig API.
MLIR_CAPI_EXPORTED bool mlirGreedyRewriteDriverConfigIsConstantCSEEnabled(MlirGreedyRewriteDriverConfig config)
Gets whether constant CSE is enabled.
MLIR_CAPI_EXPORTED void mlirRewritePatternSetAdd(MlirRewritePatternSet set, MlirRewritePattern pattern)
Add the given MlirRewritePattern into a MlirRewritePatternSet.
MLIR_CAPI_EXPORTED void mlirWalkAndApplyPatterns(MlirOperation op, MlirFrozenRewritePatternSet patterns)
Applies the given patterns to the given op by a fast walk-based pattern rewrite driver.
MLIR_CAPI_EXPORTED void mlirGreedyRewriteDriverConfigSetRegionSimplificationLevel(MlirGreedyRewriteDriverConfig config, MlirGreedySimplifyRegionLevel level)
Sets the region simplification level.
MLIR_CAPI_EXPORTED MlirLogicalResult mlirApplyPatternsAndFoldGreedily(MlirModule op, MlirFrozenRewritePatternSet patterns, MlirGreedyRewriteDriverConfig config)
MLIR_CAPI_EXPORTED void mlirGreedyRewriteDriverConfigDestroy(MlirGreedyRewriteDriverConfig config)
Destroys a greedy rewrite driver configuration.
MLIR_CAPI_EXPORTED void mlirGreedyRewriteDriverConfigSetUseTopDownTraversal(MlirGreedyRewriteDriverConfig config, bool useTopDownTraversal)
Sets whether to use top-down traversal for the initial population of the worklist.
MLIR_CAPI_EXPORTED void mlirRewriterBaseEraseOp(MlirRewriterBase rewriter, MlirOperation op)
Erases an operation that is known to have no uses.
MLIR_CAPI_EXPORTED void mlirGreedyRewriteDriverConfigSetMaxIterations(MlirGreedyRewriteDriverConfig config, int64_t maxIterations)
Sets the maximum number of iterations for the greedy rewrite driver.
MLIR_CAPI_EXPORTED MlirRewritePattern mlirOpRewritePatternCreate(MlirStringRef rootName, unsigned benefit, MlirContext context, MlirRewritePatternCallbacks callbacks, void *userData, size_t nGeneratedNames, MlirStringRef *generatedNames)
Create a rewrite pattern that matches the operation with the given rootName, corresponding to mlir::O...
MLIR_CAPI_EXPORTED MlirContext mlirRewriterBaseGetContext(MlirRewriterBase rewriter)
RewriterBase API inherited from OpBuilder.
MLIR_CAPI_EXPORTED void mlirRewriterBaseReplaceOpWithOperation(MlirRewriterBase rewriter, MlirOperation op, MlirOperation newOp)
Replace the results of the given (original) operation with the specified new op (replacement).
MLIR_CAPI_EXPORTED int64_t mlirGreedyRewriteDriverConfigGetMaxIterations(MlirGreedyRewriteDriverConfig config)
Gets the maximum number of iterations for the greedy rewrite driver.
MLIR_CAPI_EXPORTED MlirGreedyRewriteStrictness mlirGreedyRewriteDriverConfigGetStrictness(MlirGreedyRewriteDriverConfig config)
Gets the strictness level for the greedy rewrite driver.
MLIR_CAPI_EXPORTED MlirBlock mlirRewriterBaseGetInsertionBlock(MlirRewriterBase rewriter)
Return the block the current insertion point belongs to.
MLIR_CAPI_EXPORTED void mlirGreedyRewriteDriverConfigSetStrictness(MlirGreedyRewriteDriverConfig config, MlirGreedyRewriteStrictness strictness)
Sets the strictness level for the greedy rewrite driver.
MLIR_CAPI_EXPORTED void mlirRewritePatternSetDestroy(MlirRewritePatternSet set)
Destruct the given MlirRewritePatternSet.
MLIR_CAPI_EXPORTED MlirRewriterBase mlirPatternRewriterAsBase(MlirPatternRewriter rewriter)
PatternRewriter API.
MLIR_CAPI_EXPORTED MlirLogicalResult mlirApplyPatternsAndFoldGreedilyWithOp(MlirOperation op, MlirFrozenRewritePatternSet patterns, MlirGreedyRewriteDriverConfig)
MLIR_CAPI_EXPORTED bool mlirGreedyRewriteDriverConfigGetUseTopDownTraversal(MlirGreedyRewriteDriverConfig config)
Gets whether top-down traversal is used for initial worklist population.
MLIR_CAPI_EXPORTED MlirRewritePatternSet mlirRewritePatternSetCreate(MlirContext context)
RewritePatternSet API.
MLIR_CAPI_EXPORTED void mlirGreedyRewriteDriverConfigSetMaxNumRewrites(MlirGreedyRewriteDriverConfig config, int64_t maxNumRewrites)
Sets the maximum number of rewrites within an iteration.
MLIR_CAPI_EXPORTED void mlirGreedyRewriteDriverConfigEnableFolding(MlirGreedyRewriteDriverConfig config, bool enable)
Enables or disables folding during greedy rewriting.
MLIR_CAPI_EXPORTED void mlirFrozenRewritePatternSetDestroy(MlirFrozenRewritePatternSet set)
Destroy the given MlirFrozenRewritePatternSet.
MLIR_CAPI_EXPORTED MlirFrozenRewritePatternSet mlirFreezeRewritePattern(MlirRewritePatternSet set)
FrozenRewritePatternSet API.
MlirGreedySimplifyRegionLevel
Greedy simplify region levels.
@ MLIR_GREEDY_SIMPLIFY_REGION_LEVEL_DISABLED
Disable region control-flow simplification.
@ MLIR_GREEDY_SIMPLIFY_REGION_LEVEL_NORMAL
Run the normal simplification (e.g. dead args elimination).
@ MLIR_GREEDY_SIMPLIFY_REGION_LEVEL_AGGRESSIVE
Run extra simplifications (e.g. block merging).
MlirGreedyRewriteStrictness
Greedy rewrite strictness levels.
@ MLIR_GREEDY_REWRITE_STRICTNESS_EXISTING_AND_NEW_OPS
Only pre-existing and newly created ops are processed.
@ MLIR_GREEDY_REWRITE_STRICTNESS_EXISTING_OPS
Only pre-existing ops are processed.
@ MLIR_GREEDY_REWRITE_STRICTNESS_ANY_OP
No restrictions wrt. which ops are processed.
MLIR_CAPI_EXPORTED int64_t mlirGreedyRewriteDriverConfigGetMaxNumRewrites(MlirGreedyRewriteDriverConfig config)
Gets the maximum number of rewrites within an iteration.
static bool mlirTypeIsNull(MlirType type)
Checks whether a type is null.
MLIR_CAPI_EXPORTED MlirOperation mlirBlockGetParentOperation(MlirBlock)
Returns the closest surrounding operation that contains this block.
static MlirStringRef mlirStringRefCreate(const char *str, size_t length)
Constructs a string reference from the pointer and length.
static MlirLogicalResult mlirLogicalResultFailure(void)
Creates a logical result representing a failure.
struct MlirLogicalResult MlirLogicalResult
static MlirLogicalResult mlirLogicalResultSuccess(void)
Creates a logical result representing a success.
struct MlirStringRef MlirStringRef
static bool mlirLogicalResultIsFailure(MlirLogicalResult res)
Checks if the given logical result represents a failure.
PyObjectRef< PyMlirContext > PyMlirContextRef
Wrapper around MlirContext.
void populateRewriteSubmodule(nanobind::module_ &m)
Include the generated interface declarations.
const FrozenRewritePatternSet GreedyRewriteConfig config
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
MlirLogicalResult(* matchAndRewrite)(MlirRewritePattern pattern, MlirOperation op, MlirPatternRewriter rewriter, void *userData)
The callback function to match against code rooted at the specified operation, and perform the rewrit...
void(* construct)(void *userData)
Optional constructor for the user data.
void(* destruct)(void *userData)
Optional destructor for the user data.