[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