[Mlir-commits] [mlir] [mlir][linalg] Add constant folder for linalg.elementwise ops (PR #203608)

Vinit Deodhar llvmlistbot at llvm.org
Fri Jun 26 08:46:40 PDT 2026


================
@@ -145,4 +145,117 @@ func.func @named_transpose_fold_2d_fp32(%init: tensor<3x2xf32>) -> tensor<3x2xf3
 
 // -----
 
+// CHECK-LABEL: @elementwise_fold_add_f32
+func.func @elementwise_fold_add_f32(%init: tensor<4xf32>) -> tensor<4xf32> {
+  %lhs = arith.constant dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
+  %rhs = arith.constant dense<[5.0, 6.0, 7.0, 8.0]> : tensor<4xf32>
+  //               CHECK: %[[CST:.+]] = arith.constant
+  // CHECK-SAME{LITERAL}:   dense<[6.000000e+00, 8.000000e+00, 1.000000e+01, 1.200000e+01]> : tensor<4xf32>
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<add>
+    ins(%lhs, %rhs : tensor<4xf32>, tensor<4xf32>)
+    outs(%init : tensor<4xf32>) -> tensor<4xf32>
+  // CHECK: return %[[CST]]
+  return %1 : tensor<4xf32>
+}
+
+// -----
+
+// CHECK-LABEL: @elementwise_fold_mul_i32
+func.func @elementwise_fold_mul_i32(%init: tensor<3xi32>) -> tensor<3xi32> {
+  %lhs = arith.constant dense<[2, 3, 4]> : tensor<3xi32>
+  %rhs = arith.constant dense<[5, 6, 7]> : tensor<3xi32>
+  //               CHECK: %[[CST:.+]] = arith.constant
+  // CHECK-SAME{LITERAL}:   dense<[10, 18, 28]> : tensor<3xi32>
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<mul>
+    ins(%lhs, %rhs : tensor<3xi32>, tensor<3xi32>)
+    outs(%init : tensor<3xi32>) -> tensor<3xi32>
+  // CHECK: return %[[CST]]
+  return %1 : tensor<3xi32>
+}
+
+// -----
+
+// CHECK-LABEL: @elementwise_fold_sub_f64
+func.func @elementwise_fold_sub_f64(%init: tensor<2x2xf64>) -> tensor<2x2xf64> {
+  %lhs = arith.constant dense<[[10.0, 20.0], [30.0, 40.0]]> : tensor<2x2xf64>
+  %rhs = arith.constant dense<[[1.0, 2.0], [3.0, 4.0]]> : tensor<2x2xf64>
+  //               CHECK: %[[CST:.+]] = arith.constant
+  // CHECK-SAME{LITERAL}:   dense<[[9.000000e+00, 1.800000e+01], [2.700000e+01, 3.600000e+01]]> : tensor<2x2xf64>
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<sub>
+    ins(%lhs, %rhs : tensor<2x2xf64>, tensor<2x2xf64>)
+    outs(%init : tensor<2x2xf64>) -> tensor<2x2xf64>
+  // CHECK: return %[[CST]]
+  return %1 : tensor<2x2xf64>
+}
+
+// -----
+
+// CHECK-LABEL: @elementwise_fold_sin_f32
+func.func @elementwise_fold_sin_f32(%init: tensor<4xf32>) -> tensor<4xf32> {
+  %input = arith.constant dense<[0.0, 1.0, 2.0, 3.0]> : tensor<4xf32>
+  //               CHECK: %[[CST:.+]] = arith.constant
+  // CHECK-SAME{LITERAL}:   dense<[0.000000e+00, 0.841470957, 0.909297406, 1.411200e-01]> : tensor<4xf32>
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<sin>
+    ins(%input : tensor<4xf32>)
+    outs(%init : tensor<4xf32>) -> tensor<4xf32>
+  // CHECK: return %[[CST]]
+  return %1 : tensor<4xf32>
+}
+
+// -----
+
+// CHECK-LABEL: @elementwise_fold_cos_f32
+func.func @elementwise_fold_cos_f32(%init: tensor<4xf32>) -> tensor<4xf32> {
+  %input = arith.constant dense<[0.0, 1.0, 2.0, 3.0]> : tensor<4xf32>
+  //               CHECK: %[[CST:.+]] = arith.constant
+  // CHECK-SAME{LITERAL}:   dense<[1.000000e+00, 0.540302277, -0.416146845, -0.989992499]> : tensor<4xf32>
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<cos>
+    ins(%input : tensor<4xf32>)
+    outs(%init : tensor<4xf32>) -> tensor<4xf32>
+  // CHECK: return %[[CST]]
+  return %1 : tensor<4xf32>
+}
+
+// -----
+
+// CHECK-LABEL: @elementwise_nofold_non_cst_input
+func.func @elementwise_nofold_non_cst_input(%input: tensor<4xf32>, %init: tensor<4xf32>) -> tensor<4xf32> {
+  %rhs = arith.constant dense<[5.0, 6.0, 7.0, 8.0]> : tensor<4xf32>
+  // CHECK: linalg.elementwise
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<add>
+    ins(%input, %rhs : tensor<4xf32>, tensor<4xf32>)
+    outs(%init : tensor<4xf32>) -> tensor<4xf32>
+  return %1 : tensor<4xf32>
+}
+
+// -----
+
+// Verify that multi-use constants are not folded (controlFn requires single use).
+// CHECK-LABEL: @elementwise_nofold_multi_use_cst
+func.func @elementwise_nofold_multi_use_cst(%init1: tensor<4xf32>, %init2: tensor<4xf32>) -> (tensor<4xf32>, tensor<4xf32>) {
+  %cst = arith.constant dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
+  // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<sin>
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<sin>
+    ins(%cst : tensor<4xf32>)
+    outs(%init1 : tensor<4xf32>) -> tensor<4xf32>
+  // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<cos>
+  %2 = linalg.elementwise kind=#linalg.elementwise_kind<cos>
+    ins(%cst : tensor<4xf32>)
+    outs(%init2 : tensor<4xf32>) -> tensor<4xf32>
+  return %1, %2 : tensor<4xf32>, tensor<4xf32>
+}
+
+// -----
+
+// CHECK-LABEL: @elementwise_nofold_select_mixed_types
----------------
vinitdeodhar wrote:

The current limitation is in FoldConstantBase which requires all operand element types to be equal. This was fine for transpose but is overly conservative for elementwise. I'll address this in a follow-up along with the matchOp change if that is okay

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


More information about the Mlir-commits mailing list