[Mlir-commits] [mlir] [MLIR][Python] Support dialect conversion in python bindings (PR #177782)

Maksim Levental llvmlistbot at llvm.org
Sun Jan 25 15:19:30 PST 2026


================
@@ -409,9 +582,97 @@ void populateRewriteSubmodule(nb::module_ &m) {
                   If possible, the operation is cast to its corresponding OpView subclass
                   before being passed to the callable.
               benefit: The benefit of the pattern, defaulting to 1.)")
+      .def(
+          "add_conversion",
+          [](PyRewritePatternSet &self, nb::handle root, const nb::callable &fn,
+             PyTypeConverter &typeConverter, unsigned benefit) {
+            std::string opName =
+                nb::cast<std::string>(root.attr("OPERATION_NAME"));
+            self.addConversion(
+                mlirStringRefCreate(opName.data(), opName.size()), benefit, fn,
+                typeConverter);
+          },
+          "root"_a, "fn"_a, "type_converter"_a, "benefit"_a = 1,
+          R"(
+            Add a new conversion pattern on the specified root operation,
+            using the provided callable for matching and rewriting,
+            and assign it the given benefit.
+
+            Args:
+              root: The root operation to which this pattern applies.
+                    This may be either an OpView subclass (e.g., ``arith.AddIOp``) or
+                    an operation name string (e.g., ``"arith.addi"``).
+              fn: The callable to use for matching and rewriting,
+                  which takes an operation, its adaptor,
+                  the type converter and a pattern rewriter as arguments.
+                  The match is considered successful iff the callable returns
+                  a value where ``bool(value)`` is ``False`` (e.g. ``None``).
+                  If possible, the operation is cast to its corresponding OpView subclass
+                  before being passed to the callable.
+              type_converter: The type converter to convert types in the IR.
+              benefit: The benefit of the pattern, defaulting to 1.)")
       .def("freeze", &PyRewritePatternSet::freeze,
            "Freeze the pattern set into a frozen one.");
 
+  nb::class_<PyConversionPatternRewriter, PyPatternRewriter>(
+      m, "ConversionPatternRewriter");
+
+  nb::class_<PyConversionTarget>(m, "ConversionTarget")
+      .def(
+          "__init__",
+          [](PyConversionTarget &self, DefaultingPyMlirContext context) {
+            new (&self) PyConversionTarget(context.get()->get());
+          },
+          "context"_a = nb::none())
+      .def(
+          "add_legal_op",
+          [](PyConversionTarget &self, const nb::args &ops) {
+            for (auto op : ops) {
+              std::string opName =
+                  nb::cast<std::string>(op.attr("OPERATION_NAME"));
+              self.addLegalOp(opName);
+            }
+          },
+          "ops"_a, "Mark the given operations as legal.")
+      .def(
+          "add_illegal_op",
+          [](PyConversionTarget &self, const nb::args &ops) {
+            for (auto op : ops) {
+              std::string opName =
+                  nb::cast<std::string>(op.attr("OPERATION_NAME"));
+              self.addIllegalOp(opName);
+            }
+          },
+          "ops"_a, "Mark the given operations as illegal.")
+      .def(
+          "add_legal_dialect",
+          [](PyConversionTarget &self, const nb::args &dialects) {
+            for (auto dialect : dialects) {
+              std::string dialectName =
+                  nb::cast<std::string>(dialect.attr("DIALECT_NAMESPACE"));
+              self.addLegalDialect(dialectName);
+            }
+          },
+          "dialects"_a, "Mark the given dialects as legal.")
+      .def(
+          "add_illegal_dialect",
+          [](PyConversionTarget &self, const nb::args &dialects) {
+            for (auto dialect : dialects) {
+              std::string dialectName =
+                  nb::cast<std::string>(dialect.attr("DIALECT_NAMESPACE"));
+              self.addIllegalDialect(dialectName);
+            }
+          },
+          "dialects"_a, "Mark the given dialect as illegal.");
+
+  nb::class_<PyTypeConverter>(m, "TypeConverter")
+      .def(
+          "__init__",
+          [](PyTypeConverter &self) { new (&self) PyTypeConverter(); },
----------------
makslevental wrote:

um why explicitly? can't you just do `.def(nb::init<>())`?

https://github.com/llvm/llvm-project/pull/177782


More information about the Mlir-commits mailing list