[Mlir-commits] [mlir] ch2 : add div op (PR #226454)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sun Sep 27 00:55:24 PDT 2026


https://github.com/Kamalraj78 updated https://github.com/llvm/llvm-project/pull/226454

>From 50bc7b3800f31c4ae93adb099867020a86de463a Mon Sep 17 00:00:00 2001
From: Kamalraj <kamalraj20122001 at gmail.com>
Date: Fri, 25 Sep 2026 17:11:38 +0530
Subject: [PATCH 1/2] ch2 : add div op(Hands-on)

---
 mlir/examples/toy/Ch2/include/toy/Ops.td   | 12 ++++++++++++
 mlir/examples/toy/Ch2/include/toy/Parser.h |  3 +++
 mlir/examples/toy/Ch2/mlir/Dialect.cpp     | 20 ++++++++++++++++++++
 mlir/examples/toy/Ch2/mlir/MLIRGen.cpp     |  7 +++++--
 mlir/test/Examples/Toy/Ch2/div.toy         |  6 ++++++
 5 files changed, 46 insertions(+), 2 deletions(-)
 create mode 100644 mlir/test/Examples/Toy/Ch2/div.toy

diff --git a/mlir/examples/toy/Ch2/include/toy/Ops.td b/mlir/examples/toy/Ch2/include/toy/Ops.td
index 59106aa1622c9..d229ee3dd0d65 100644
--- a/mlir/examples/toy/Ch2/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch2/include/toy/Ops.td
@@ -108,6 +108,18 @@ def AddOp : Toy_Op<"add"> {
   ];
 }
 
+//===----------------------------------------------------------------------===//
+// DivOp
+//===----------------------------------------------------------------------===//
+
+def DivOp : Toy_Op<"div"> {
+  let summary = "element-wise division operation";
+  let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
+  let results = (outs F64Tensor);
+  let builders = [OpBuilder<(ins "Value":$lhs, "Value":$rhs)>];
+  let hasCustomAssemblyFormat = 1;  
+}
+
 //===----------------------------------------------------------------------===//
 // FuncOp
 //===----------------------------------------------------------------------===//
diff --git a/mlir/examples/toy/Ch2/include/toy/Parser.h b/mlir/examples/toy/Ch2/include/toy/Parser.h
index 1f20616ac6b4e..fce38d78e9baa 100644
--- a/mlir/examples/toy/Ch2/include/toy/Parser.h
+++ b/mlir/examples/toy/Ch2/include/toy/Parser.h
@@ -463,6 +463,9 @@ class Parser {
       return 20;
     case '*':
       return 40;
+    // support '/' as a binary operator, same precedence as '*'
+    case '/':
+      return 40;
     default:
       return -1;
     }
diff --git a/mlir/examples/toy/Ch2/mlir/Dialect.cpp b/mlir/examples/toy/Ch2/mlir/Dialect.cpp
index f86e1e7fc7430..86ceb272919df 100644
--- a/mlir/examples/toy/Ch2/mlir/Dialect.cpp
+++ b/mlir/examples/toy/Ch2/mlir/Dialect.cpp
@@ -252,6 +252,26 @@ mlir::ParseResult MulOp::parse(mlir::OpAsmParser &parser,
 
 void MulOp::print(mlir::OpAsmPrinter &p) { printBinaryOp(p, *this); }
 
+
+//===----------------------------------------------------------------------===//
+// DivOp: reuse binary-op build/parse/print helpers, same pattern as AddOp/MulOp
+//===----------------------------------------------------------------------===//
+
+void DivOp::build(mlir::OpBuilder &builder, mlir::OperationState &state,
+                   mlir::Value lhs, mlir::Value rhs) {
+  state.addTypes(UnrankedTensorType::get(builder.getF64Type()));
+  state.addOperands({lhs, rhs});
+}
+
+mlir::ParseResult DivOp::parse(mlir::OpAsmParser &parser,
+                                mlir::OperationState &result) {
+  return parseBinaryOp(parser, result);
+}
+
+void DivOp::print(mlir::OpAsmPrinter &printer) {
+  printBinaryOp(printer, *this);
+}
+
 //===----------------------------------------------------------------------===//
 // ReturnOp
 //===----------------------------------------------------------------------===//
diff --git a/mlir/examples/toy/Ch2/mlir/MLIRGen.cpp b/mlir/examples/toy/Ch2/mlir/MLIRGen.cpp
index a9592bcd7814a..5b2c4e46d8ac8 100644
--- a/mlir/examples/toy/Ch2/mlir/MLIRGen.cpp
+++ b/mlir/examples/toy/Ch2/mlir/MLIRGen.cpp
@@ -198,13 +198,16 @@ class MLIRGenImpl {
       return nullptr;
     auto location = loc(binop.loc());
 
-    // Derive the operation name from the binary operator. At the moment we only
-    // support '+' and '*'.
+    // Derive the operation name from the binary operator. At the moment we
+    // support '+', '*' and '/'.
     switch (binop.getOp()) {
     case '+':
       return AddOp::create(builder, location, lhs, rhs);
     case '*':
       return MulOp::create(builder, location, lhs, rhs);
+    // emit toy.div for '/'
+    case '/':
+      return DivOp::create(builder, location, lhs, rhs);
     }
 
     emitError(location, "invalid binary operator '") << binop.getOp() << "'";
diff --git a/mlir/test/Examples/Toy/Ch2/div.toy b/mlir/test/Examples/Toy/Ch2/div.toy
new file mode 100644
index 0000000000000..28211ce51dcd6
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch2/div.toy
@@ -0,0 +1,6 @@
+def main() {
+  var a = 10;
+  var b = 2;
+  var c = a / b;
+  print(c);
+}
\ No newline at end of file

>From c1cba5236d9392184bdbc70b62ae1f45628319e1 Mon Sep 17 00:00:00 2001
From: Kamalraj <kamalraj20122001 at gmail.com>
Date: Sun, 27 Sep 2026 13:23:08 +0530
Subject: [PATCH 2/2] Ch3: add canonicalization pattern div(x, 1) -> x

---
 mlir/examples/toy/Ch3/include/toy/Ops.td   | 13 +++++++++++
 mlir/examples/toy/Ch3/include/toy/Parser.h |  3 +++
 mlir/examples/toy/Ch3/mlir/Dialect.cpp     | 20 ++++++++++++++++
 mlir/examples/toy/Ch3/mlir/MLIRGen.cpp     |  7 ++++--
 mlir/examples/toy/Ch3/mlir/ToyCombine.cpp  | 27 ++++++++++++++++++++++
 mlir/test/Examples/Toy/Ch3/div.toy         |  6 +++++
 6 files changed, 74 insertions(+), 2 deletions(-)
 create mode 100644 mlir/test/Examples/Toy/Ch3/div.toy

diff --git a/mlir/examples/toy/Ch3/include/toy/Ops.td b/mlir/examples/toy/Ch3/include/toy/Ops.td
index e0e973a96ed88..f4afdf6fc89c2 100644
--- a/mlir/examples/toy/Ch3/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch3/include/toy/Ops.td
@@ -224,6 +224,19 @@ def MulOp : Toy_Op<"mul", [Pure]> {
   ];
 }
 
+//===----------------------------------------------------------------------===//
+// DivOp
+//===----------------------------------------------------------------------===//
+
+def DivOp : Toy_Op<"div"> {
+  let summary = "element-wise division operation";
+  let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
+  let results = (outs F64Tensor);
+  let builders = [OpBuilder<(ins "Value":$lhs, "Value":$rhs)>];
+  let hasCustomAssemblyFormat = 1;  
+  let hasCanonicalizer = 1; // let DivOp register rewrite patterns
+}
+
 //===----------------------------------------------------------------------===//
 // PrintOp
 //===----------------------------------------------------------------------===//
diff --git a/mlir/examples/toy/Ch3/include/toy/Parser.h b/mlir/examples/toy/Ch3/include/toy/Parser.h
index 1f20616ac6b4e..fce38d78e9baa 100644
--- a/mlir/examples/toy/Ch3/include/toy/Parser.h
+++ b/mlir/examples/toy/Ch3/include/toy/Parser.h
@@ -463,6 +463,9 @@ class Parser {
       return 20;
     case '*':
       return 40;
+    // support '/' as a binary operator, same precedence as '*'
+    case '/':
+      return 40;
     default:
       return -1;
     }
diff --git a/mlir/examples/toy/Ch3/mlir/Dialect.cpp b/mlir/examples/toy/Ch3/mlir/Dialect.cpp
index f8aaf20fbd125..064fff77a6b8b 100644
--- a/mlir/examples/toy/Ch3/mlir/Dialect.cpp
+++ b/mlir/examples/toy/Ch3/mlir/Dialect.cpp
@@ -186,6 +186,26 @@ mlir::ParseResult AddOp::parse(mlir::OpAsmParser &parser,
 
 void AddOp::print(mlir::OpAsmPrinter &p) { printBinaryOp(p, *this); }
 
+//===----------------------------------------------------------------------===//
+// DivOp: reuse binary-op build/parse/print helpers, same pattern as AddOp/MulOp
+//===----------------------------------------------------------------------===//
+
+void DivOp::build(mlir::OpBuilder &builder, mlir::OperationState &state,
+                   mlir::Value lhs, mlir::Value rhs) {
+  state.addTypes(UnrankedTensorType::get(builder.getF64Type()));
+  state.addOperands({lhs, rhs});
+}
+
+mlir::ParseResult DivOp::parse(mlir::OpAsmParser &parser,
+                                mlir::OperationState &result) {
+  return parseBinaryOp(parser, result);
+}
+
+void DivOp::print(mlir::OpAsmPrinter &printer) {
+  printBinaryOp(printer, *this);
+}
+
+
 //===----------------------------------------------------------------------===//
 // FuncOp
 //===----------------------------------------------------------------------===//
diff --git a/mlir/examples/toy/Ch3/mlir/MLIRGen.cpp b/mlir/examples/toy/Ch3/mlir/MLIRGen.cpp
index 8c21951948496..d56820e3de709 100644
--- a/mlir/examples/toy/Ch3/mlir/MLIRGen.cpp
+++ b/mlir/examples/toy/Ch3/mlir/MLIRGen.cpp
@@ -198,13 +198,16 @@ class MLIRGenImpl {
       return nullptr;
     auto location = loc(binop.loc());
 
-    // Derive the operation name from the binary operator. At the moment we only
-    // support '+' and '*'.
+    // Derive the operation name from the binary operator. At the moment we
+    // support '+', '*' and '/'.
     switch (binop.getOp()) {
     case '+':
       return AddOp::create(builder, location, lhs, rhs);
     case '*':
       return MulOp::create(builder, location, lhs, rhs);
+    // emit toy.div for '/'
+    case '/':
+      return DivOp::create(builder, location, lhs, rhs);
     }
 
     emitError(location, "invalid binary operator '") << binop.getOp() << "'";
diff --git a/mlir/examples/toy/Ch3/mlir/ToyCombine.cpp b/mlir/examples/toy/Ch3/mlir/ToyCombine.cpp
index f8397c2e06490..a19c90e72c2e5 100644
--- a/mlir/examples/toy/Ch3/mlir/ToyCombine.cpp
+++ b/mlir/examples/toy/Ch3/mlir/ToyCombine.cpp
@@ -66,3 +66,30 @@ void ReshapeOp::getCanonicalizationPatterns(RewritePatternSet &results,
   results.add<ReshapeReshapeOptPattern, RedundantReshapeOptPattern,
               FoldConstantReshapeOptPattern>(context);
 }
+
+/// Fold div(x, 1) -> x
+struct SimplifyDivByOne : public mlir::OpRewritePattern<DivOp> {
+  SimplifyDivByOne(mlir::MLIRContext *context)
+      : OpRewritePattern<DivOp>(context, /*benefit=*/1) {}
+
+  mlir::LogicalResult
+  matchAndRewrite(DivOp op, mlir::PatternRewriter &rewriter) const override {
+    // Match only when rhs is a constant equal to 1.
+    auto rhsConstant = op.getRhs().getDefiningOp<ConstantOp>();
+    if (!rhsConstant)
+      return mlir::failure();
+    auto value = rhsConstant.getValue();
+    if (!value.isSplat() || value.getSplatValue<double>() != 1.0)
+      return mlir::failure();
+
+    // Replace toy.div(x, 1) with just x.
+    rewriter.replaceOp(op, op.getLhs());
+    return mlir::success();
+  }
+};
+
+// Register the pattern so the Canonicalizer pass picks it up.
+void DivOp::getCanonicalizationPatterns(mlir::RewritePatternSet &results,
+                                         mlir::MLIRContext *context) {
+  results.add<SimplifyDivByOne>(context);
+}
\ No newline at end of file
diff --git a/mlir/test/Examples/Toy/Ch3/div.toy b/mlir/test/Examples/Toy/Ch3/div.toy
new file mode 100644
index 0000000000000..09d504923a3dc
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch3/div.toy
@@ -0,0 +1,6 @@
+def main() {
+  var a = 10;
+  var b = 1;
+  var c = a / b;
+  print(c);
+}
\ No newline at end of file



More information about the Mlir-commits mailing list