[Mlir-commits] [mlir] [MLIR][EmitC] Mark CastOp as Pure (PR #202749)
Andrzej WarzyĆski
llvmlistbot at llvm.org
Wed Jun 10 09:48:01 PDT 2026
https://github.com/banach-space updated https://github.com/llvm/llvm-project/pull/202749
>From 36c29b3fe2bfe6581cb4d0a3064056b9fcc89d81 Mon Sep 17 00:00:00 2001
From: Andrzej Warzynski <andrzej.warzynski at arm.com>
Date: Tue, 9 Jun 2026 19:39:51 +0000
Subject: [PATCH 1/2] [MLIR][EmitC] Mark CastOp as Pure
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 2 +-
mlir/test/Dialect/EmitC/canonicalize.mlir | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
create mode 100644 mlir/test/Dialect/EmitC/canonicalize.mlir
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 65361a987a08e..09fad02da39b2 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -394,7 +394,7 @@ def EmitC_MemberCallOpaqueOp : EmitC_Op<"member_call_opaque", [CExpressionInterf
}
def EmitC_CastOp : EmitC_Op<"cast",
- [CExpressionInterface,
+ [Pure, CExpressionInterface,
DeclareOpInterfaceMethods<CastOpInterface>]> {
let summary = "Cast operation";
let description = [{
diff --git a/mlir/test/Dialect/EmitC/canonicalize.mlir b/mlir/test/Dialect/EmitC/canonicalize.mlir
new file mode 100644
index 0000000000000..a2c41375da398
--- /dev/null
+++ b/mlir/test/Dialect/EmitC/canonicalize.mlir
@@ -0,0 +1,9 @@
+// RUN: mlir-opt %s -canonicalize="test-convergence" -split-input-file | FileCheck %s
+
+// While there is no dedicated folder for CastOp, it is Pure and hence should
+// be "folded away".
+func.func @cast(%arg0: i32) {
+ // CHECK-NOT: emitc.cast
+ %1 = emitc.cast %arg0: i32 to f32
+ return
+}
>From 055d86ac70f53316bae75f4874a1d2cbcac64f54 Mon Sep 17 00:00:00 2001
From: Andrzej Warzynski <andrzej.warzynski at arm.com>
Date: Wed, 10 Jun 2026 16:47:36 +0000
Subject: [PATCH 2/2] Swich from unconditional PURE to opt-in
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 14 +++++++++++---
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 15 +++++++++++++++
mlir/test/Dialect/EmitC/canonicalize.mlir | 12 ++++++++----
3 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 09fad02da39b2..4527afeedc346 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -394,8 +394,11 @@ def EmitC_MemberCallOpaqueOp : EmitC_Op<"member_call_opaque", [CExpressionInterf
}
def EmitC_CastOp : EmitC_Op<"cast",
- [Pure, CExpressionInterface,
- DeclareOpInterfaceMethods<CastOpInterface>]> {
+ [CExpressionInterface,
+ DeclareOpInterfaceMethods<CastOpInterface>,
+ DeclareOpInterfaceMethods<ConditionallySpeculatable>,
+ DeclareOpInterfaceMethods<MemoryEffectsOpInterface>
+ ]> {
let summary = "Cast operation";
let description = [{
The `emitc.cast` operation performs an explicit type conversion and is emitted
@@ -414,7 +417,10 @@ def EmitC_CastOp : EmitC_Op<"cast",
```
}];
- let arguments = (ins EmitCType:$source);
+ let arguments = (ins EmitCType:$source,
+ UnitAttr:$pure
+ );
+
let results = (outs EmitCType:$dest);
let assemblyFormat = "$source attr-dict `:` type($source) `to` type($dest)";
@@ -422,6 +428,8 @@ def EmitC_CastOp : EmitC_Op<"cast",
bool hasSideEffects() {
return false;
}
+
+ bool isPure();
}];
}
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index bab9cb4a91102..288ab0fe5215f 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -336,6 +336,21 @@ bool CastOp::areCastCompatible(TypeRange inputs, TypeRange outputs) {
emitc::isSupportedFloatType(output) || isa<emitc::PointerType>(output)));
}
+bool CastOp::isPure() { return static_cast<bool>(getPureAttr()); }
+
+Speculation::Speculatability emitc::CastOp::getSpeculatability() {
+ return getPure() ? Speculation::Speculatable : Speculation::NotSpeculatable;
+}
+
+void emitc::CastOp::getEffects(
+ SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
+ if (getPure())
+ return;
+
+ effects.emplace_back(MemoryEffects::Read::get());
+ effects.emplace_back(MemoryEffects::Write::get());
+}
+
//===----------------------------------------------------------------------===//
// CallOpaqueOp
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/EmitC/canonicalize.mlir b/mlir/test/Dialect/EmitC/canonicalize.mlir
index a2c41375da398..29d2fd157229d 100644
--- a/mlir/test/Dialect/EmitC/canonicalize.mlir
+++ b/mlir/test/Dialect/EmitC/canonicalize.mlir
@@ -1,9 +1,13 @@
// RUN: mlir-opt %s -canonicalize="test-convergence" -split-input-file | FileCheck %s
-// While there is no dedicated folder for CastOp, it is Pure and hence should
-// be "folded away".
-func.func @cast(%arg0: i32) {
- // CHECK-NOT: emitc.cast
+func.func @no_fold_cast_to_f32(%arg0: i32) {
+ // CHECK: emitc.cast
%1 = emitc.cast %arg0: i32 to f32
return
}
+
+func.func @fold_cast_to_i64(%arg0: i32) {
+ // CHECK-NOT: emitc.cast
+ %1 = emitc.cast %arg0 {pure} : i32 to i64
+ return
+}
More information about the Mlir-commits
mailing list