[Mlir-commits] [mlir] [MLIR][Linalg] Remove unary named ops (PR #220905)

Renato Golin llvmlistbot at llvm.org
Wed Sep 9 07:20:34 PDT 2026


https://github.com/rengolin updated https://github.com/llvm/llvm-project/pull/220905

>From 3579c47e3851af9c37214a54bd41fb8f0feb38b0 Mon Sep 17 00:00:00 2001
From: rengolin <rengolin at systemcall.eu>
Date: Wed, 9 Sep 2026 07:13:00 -0700
Subject: [PATCH 1/2] [MLIR][Linalg] Remove unary named ops

Remove ops, change tests to elementwise to continue working as is.

Ref:
https://discourse.llvm.org/t/rfc-update-semantics-of-linalg-named-operations-unary-binary-ternary/91531
---
 .../mlir/Dialect/Linalg/IR/LinalgInterfaces.h |   2 +-
 .../Linalg/IR/LinalgNamedStructuredOps.yaml   | 457 +-----------------
 .../Dialect/Linalg/IR/LinalgInterfaces.cpp    |   4 +-
 .../Linalg/Transforms/CategoryToNamedOp.cpp   |  30 +-
 .../Linalg/Transforms/NamedToElementwise.cpp  |  28 +-
 .../Dialect/Linalg/Transforms/Specialize.cpp  |  78 +--
 .../linalg/opdsl/ops/core_named_ops.py        | 158 +-----
 .../Dialect/Bufferization/canonicalize.mlir   |   4 +-
 .../elementwise/named-to-elementwise.mlir     |  13 -
 .../Dialect/Linalg/generalize-named-ops.mlir  | 275 -----------
 .../Linalg/linalg-morph-category-ops.mlir     |  15 -
 .../linalg-morph-elementwise-to-named.mlir    |  81 +---
 .../Linalg/linalg-morph-multi-step.mlir       |  51 --
 .../Dialect/Linalg/match-ops-interpreter.mlir |   6 +-
 mlir/test/Dialect/Linalg/named-ops-fail.mlir  | 208 --------
 mlir/test/Dialect/Linalg/named-ops.mlir       | 403 ---------------
 ...oundtrip-morphism-linalg-category-ops.mlir |   6 -
 .../roundtrip-morphism-linalg-named-ops.mlir  |  62 ---
 .../scalable-unpack-producer-fusion.mlir      |  30 +-
 .../Linalg/specialize-generic-ops.mlir        |  97 +---
 .../transform-op-fuse-into-containing.mlir    |  36 +-
 .../Dialect/Linalg/transform-op-fuse.mlir     | 126 ++---
 .../Linalg/transform-op-generalize.mlir       |   4 +-
 ...ransform-op-specialize-elemwise-unary.mlir | 122 -----
 mlir/test/Dialect/SCF/canonicalize.mlir       |   8 +-
 .../Dialect/SCF/parallel-loop-unroll.mlir     |  12 +-
 .../tile-and-fuse-consumer-using-slices.mlir  |  20 +-
 .../tile-and-fuse-consumer.mlir               |  22 +-
 .../linalg/opdsl/test_core_named_ops.py       |   3 +-
 29 files changed, 195 insertions(+), 2166 deletions(-)
 delete mode 100644 mlir/test/Dialect/Linalg/linalg-morph-category-ops.mlir
 delete mode 100644 mlir/test/Dialect/Linalg/transform-op-specialize-elemwise-unary.mlir

diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.h b/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.h
index 9ff32216ce042..682d016849e88 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.h
+++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.h
@@ -147,7 +147,7 @@ std::optional<SmallVector<int64_t>>
 isaTransposeOpInterface(GenericOp genericOp);
 
 /// Checks whether a given `genericOp` is semantically equivalent to a single
-/// linalg elementwise unary op, e.g. `linalg.exp` or
+/// linalg elementwise unary op, e.g.
 /// `linalg.elementwise kind=#linalg.elementwise_kind<exp>`.
 /// If `allowNonIdentityMaps` is true, operations with custom indexing maps are
 /// included in the check. Note that these operations can only be represented by
diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml b/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml
index 521afc991063f..5514ba3afcf37 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml
+++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml
@@ -44,461 +44,6 @@ structured_op: !LinalgStructuredOpConfig
         - !ScalarExpression
           scalar_arg: I
 --- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: exp
-  cpp_class_name: ExpOp
-  doc: |-
-    Applies exp(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: exp
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: log
-  cpp_class_name: LogOp
-  doc: |-
-    Applies log(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: log
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: abs
-  cpp_class_name: AbsOp
-  doc: |-
-    Applies abs(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: abs
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: ceil
-  cpp_class_name: CeilOp
-  doc: |-
-    Applies ceil(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: ceil
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: floor
-  cpp_class_name: FloorOp
-  doc: |-
-    Applies floor(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: floor
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: negf
-  cpp_class_name: NegFOp
-  doc: |-
-    Applies negf(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: negf
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: reciprocal
-  cpp_class_name: ReciprocalOp
-  doc: |-
-    Applies reciprocal(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: reciprocal
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: round
-  cpp_class_name: RoundOp
-  doc: |-
-    Applies round(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: round
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: sqrt
-  cpp_class_name: SqrtOp
-  doc: |-
-    Applies sqrt(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: sqrt
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: rsqrt
-  cpp_class_name: RsqrtOp
-  doc: |-
-    Applies rsqrt(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: rsqrt
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: square
-  cpp_class_name: SquareOp
-  doc: |-
-    Applies square(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: square
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: tanh
-  cpp_class_name: TanhOp
-  doc: |-
-    Applies tanh(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: tanh
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
-  name: erf
-  cpp_class_name: ErfOp
-  doc: |-
-    Applies erf(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-structured_op: !LinalgStructuredOpConfig
-  args:
-  - !LinalgOperandDefConfig
-    name: I
-    kind: input_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  - !LinalgOperandDefConfig
-    name: O
-    kind: output_tensor
-    type_var: T1
-    shape_map: affine_map<() -> ()>
-  indexing_maps: !LinalgIndexingMapsConfig
-    static_indexing_maps:
-    - affine_map<() -> ()>
-    - affine_map<() -> ()>
-  iterator_types: []
-  assignments:
-  - !ScalarAssign
-    arg: O
-    value: !ScalarExpression
-      scalar_fn:
-        kind: unary
-        fn_name: erf
-        operands:
-        - !ScalarExpression
-          scalar_arg: I
---- !LinalgOpConfig
 metadata: !LinalgOpMetadata
   name: add
   cpp_class_name: AddOp
@@ -847,7 +392,7 @@ metadata: !LinalgOpMetadata
   name: powf
   cpp_class_name: PowFOp
   doc: |-
-    Takes the powf(lhs, rhs) between two inputs, elementwise. For powf(arg, 2) use `linalg.square`.
+    Takes the powf(lhs, rhs) between two inputs, elementwise. For powf(arg, 2) use `linalg.elementwise kind=square`.
 
     Only applies to floating point values.
 
diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp
index 3045e65630cf2..cff613f389669 100644
--- a/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp
+++ b/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp
@@ -256,8 +256,8 @@ isaElemwiseSingleUnaryOrBinaryOpInterface(linalg::GenericOp op, unsigned arity,
 
   // The payload op must have one result and at least arity-many operands
   // (otherwise not all inputs can be used). It can have additional operands
-  // from outside of the generic op (e.g. div(1, x) for linalg.reciprocal) or
-  // use an input more than once (e.g. mul(x, x) for linalg.square).
+  // from outside of the generic op (e.g. div(1, x) for elementwise reciprocal)
+  // or use an input more than once (e.g. mul(x, x) for elementwise square).
   Operation *oper = &body->front();
   if (oper->getNumOperands() < arity || oper->getNumResults() != 1)
     return false;
diff --git a/mlir/lib/Dialect/Linalg/Transforms/CategoryToNamedOp.cpp b/mlir/lib/Dialect/Linalg/Transforms/CategoryToNamedOp.cpp
index 6d1f61100dbf5..711069caff7c4 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/CategoryToNamedOp.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/CategoryToNamedOp.cpp
@@ -7,8 +7,8 @@
 //===----------------------------------------------------------------------===//
 //
 // This file implements rewriting of linalg category ops (e.g.
-// `linalg.elementwise`) to their equivalent named ops (e.g. `linalg.add`,
-// `linalg.exp`). This is the reverse of NamedToElementwise.cpp.
+// `linalg.elementwise`) to their equivalent named ops (e.g. `linalg.add`).
+// This is the reverse of NamedToElementwise.cpp.
 //
 //===----------------------------------------------------------------------===//
 
@@ -46,32 +46,6 @@ struct ElementwiseToNamedPattern : public OpRewritePattern<ElementwiseOp> {
     };
 
     switch (op.getKind()) {
-    case ElementwiseKind::exp:
-      return replaceWith(ExpOp{});
-    case ElementwiseKind::log:
-      return replaceWith(LogOp{});
-    case ElementwiseKind::abs:
-      return replaceWith(AbsOp{});
-    case ElementwiseKind::ceil:
-      return replaceWith(CeilOp{});
-    case ElementwiseKind::floor:
-      return replaceWith(FloorOp{});
-    case ElementwiseKind::negf:
-      return replaceWith(NegFOp{});
-    case ElementwiseKind::reciprocal:
-      return replaceWith(ReciprocalOp{});
-    case ElementwiseKind::round:
-      return replaceWith(RoundOp{});
-    case ElementwiseKind::sqrt:
-      return replaceWith(SqrtOp{});
-    case ElementwiseKind::rsqrt:
-      return replaceWith(RsqrtOp{});
-    case ElementwiseKind::square:
-      return replaceWith(SquareOp{});
-    case ElementwiseKind::tanh:
-      return replaceWith(TanhOp{});
-    case ElementwiseKind::erf:
-      return replaceWith(ErfOp{});
     case ElementwiseKind::add:
       return replaceWith(AddOp{});
     case ElementwiseKind::sub:
diff --git a/mlir/lib/Dialect/Linalg/Transforms/NamedToElementwise.cpp b/mlir/lib/Dialect/Linalg/Transforms/NamedToElementwise.cpp
index c9045566473cb..b2687cb4dc87b 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/NamedToElementwise.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/NamedToElementwise.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 //
 // This file implements rewriting those linalg named ops that are essentially
-// elementwise e.g. `linalg.exp`, to `linalg.elementwise`. This allows further
+// elementwise e.g. `linalg.add`, to `linalg.elementwise`. This allows further
 // optimization on `linalg.elementwise` such as folding transpose, broadcast.
 //
 //===----------------------------------------------------------------------===//
@@ -35,19 +35,6 @@ ElementwiseKind getKind(Operation *op) {
       .Case([](DivOp) { return ElementwiseKind::div; })
       .Case([](DivUnsignedOp) { return ElementwiseKind::div_unsigned; })
       .Case([](PowFOp) { return ElementwiseKind::powf; })
-      .Case([](ExpOp) { return ElementwiseKind::exp; })
-      .Case([](LogOp) { return ElementwiseKind::log; })
-      .Case([](AbsOp) { return ElementwiseKind::abs; })
-      .Case([](CeilOp) { return ElementwiseKind::ceil; })
-      .Case([](FloorOp) { return ElementwiseKind::floor; })
-      .Case([](NegFOp) { return ElementwiseKind::negf; })
-      .Case([](ReciprocalOp) { return ElementwiseKind::reciprocal; })
-      .Case([](RoundOp) { return ElementwiseKind::round; })
-      .Case([](SqrtOp) { return ElementwiseKind::sqrt; })
-      .Case([](RsqrtOp) { return ElementwiseKind::rsqrt; })
-      .Case([](SquareOp) { return ElementwiseKind::square; })
-      .Case([](TanhOp) { return ElementwiseKind::tanh; })
-      .Case([](ErfOp) { return ElementwiseKind::erf; })
       .DefaultUnreachable("unhandled case in named to elementwise");
 }
 
@@ -79,17 +66,4 @@ void mlir::linalg::populateLinalgNamedToElementwisePatterns(
   patterns.add<NamedToElementwisePattern<DivOp>>(patterns.getContext());
   patterns.add<NamedToElementwisePattern<DivUnsignedOp>>(patterns.getContext());
   patterns.add<NamedToElementwisePattern<PowFOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<ExpOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<LogOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<AbsOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<CeilOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<FloorOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<NegFOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<ReciprocalOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<RoundOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<SqrtOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<RsqrtOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<SquareOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<TanhOp>>(patterns.getContext());
-  patterns.add<NamedToElementwisePattern<ErfOp>>(patterns.getContext());
 }
diff --git a/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp b/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp
index 1bdcd0be31329..a063465e1a4c9 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp
@@ -104,11 +104,12 @@ static bool findIndexOfScalarOperand(GenericOp genericOp, int &index) {
 //       linalg.yield %1 : f32
 //     } -> tensor<?x?xf32>
 //
-// is specialized to either
-//   linalg.exp ins(...) outs(...) -> ...
-// or
+// is specialized to
 //   linalg.elementwise kind=#linalg.elementwise_kind<exp> ...
 //
+// A named op is emitted instead for binary/ternary ops that still have a
+// linalg.* named equivalent (e.g. linalg.add).
+//
 // Only the category op can carry non-identity indexing maps; these are
 // transferred verbatim from the `genericOp`.
 //
@@ -191,42 +192,41 @@ static FailureOr<LinalgOp> specializeLinalgElementwise(RewriterBase &rewriter,
   };
 
   if (isUnary) {
-    if (isa<math::ExpOp>(op))
-      return replaceOp(ExpOp{}, ElementwiseKind::exp);
-    if (isa<math::LogOp>(op))
-      return replaceOp(LogOp{}, ElementwiseKind::log);
-    if (isa<math::AbsFOp>(op))
-      return replaceOp(AbsOp{}, ElementwiseKind::abs);
-    if (isa<math::CeilOp>(op))
-      return replaceOp(CeilOp{}, ElementwiseKind::ceil);
-    if (isa<math::FloorOp>(op))
-      return replaceOp(FloorOp{}, ElementwiseKind::floor);
-    if (isa<arith::NegFOp>(op))
-      return replaceOp(NegFOp{}, ElementwiseKind::negf);
-    if (auto divOp = dyn_cast<arith::DivFOp>(op)) {
-      if (auto constOp = dyn_cast_if_present<arith::ConstantOp>(
-              divOp.getLhs().getDefiningOp()))
-        if (cast<FloatAttr>(constOp.getValue()).getValue().isExactlyValue(1.0))
-          return replaceOp(ReciprocalOp{}, ElementwiseKind::reciprocal,
-                           /*mayHoistScalarOperand=*/false);
-    }
-    if (isa<math::RoundOp>(op))
-      return replaceOp(RoundOp{}, ElementwiseKind::round);
-    if (isa<math::SqrtOp>(op))
-      return replaceOp(SqrtOp{}, ElementwiseKind::sqrt);
-    if (isa<math::RsqrtOp>(op))
-      return replaceOp(RsqrtOp{}, ElementwiseKind::rsqrt);
-    if (auto mulOp = dyn_cast<arith::MulFOp>(op);
-        mulOp && mulOp.getLhs() == mulOp.getRhs())
-      return replaceOp(SquareOp{}, ElementwiseKind::square);
-    if (isa<math::TanhOp>(op))
-      return replaceOp(TanhOp{}, ElementwiseKind::tanh);
-    if (isa<math::ErfOp>(op))
-      return replaceOp(ErfOp{}, ElementwiseKind::erf);
-
-    // The following ops only have the category (elementwise) form, but no
-    // linalg.* named op equivalent.
+    // Unary ops only have the category (elementwise) form; the linalg.* named
+    // unary ops have been removed.
     if (emitCategoryOp) {
+      if (isa<math::ExpOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::exp);
+      if (isa<math::AbsFOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::abs);
+      if (isa<math::CeilOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::ceil);
+      if (isa<math::FloorOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::floor);
+      if (isa<arith::NegFOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::negf);
+      if (auto divOp = dyn_cast<arith::DivFOp>(op)) {
+        if (auto constOp = dyn_cast_if_present<arith::ConstantOp>(
+                divOp.getLhs().getDefiningOp()))
+          if (cast<FloatAttr>(constOp.getValue())
+                  .getValue()
+                  .isExactlyValue(1.0))
+            return replaceOp(nullptr, ElementwiseKind::reciprocal,
+                             /*mayHoistScalarOperand=*/false);
+      }
+      if (isa<math::RoundOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::round);
+      if (isa<math::SqrtOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::sqrt);
+      if (isa<math::RsqrtOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::rsqrt);
+      if (auto mulOp = dyn_cast<arith::MulFOp>(op);
+          mulOp && mulOp.getLhs() == mulOp.getRhs())
+        return replaceOp(nullptr, ElementwiseKind::square);
+      if (isa<math::TanhOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::tanh);
+      if (isa<math::ErfOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::erf);
       if (isa<math::SinOp>(op))
         return replaceOp(nullptr, ElementwiseKind::sin);
       if (isa<math::CosOp>(op))
@@ -245,6 +245,8 @@ static FailureOr<LinalgOp> specializeLinalgElementwise(RewriterBase &rewriter,
         return replaceOp(nullptr, ElementwiseKind::atan);
       if (isa<math::AtanhOp>(op))
         return replaceOp(nullptr, ElementwiseKind::atanh);
+      if (isa<math::LogOp>(op))
+        return replaceOp(nullptr, ElementwiseKind::log);
       if (isa<math::Log10Op>(op))
         return replaceOp(nullptr, ElementwiseKind::log10);
       if (isa<math::Log1pOp>(op))
diff --git a/mlir/python/mlir/dialects/linalg/opdsl/ops/core_named_ops.py b/mlir/python/mlir/dialects/linalg/opdsl/ops/core_named_ops.py
index 9c24f94fcf612..ab80d1d62c662 100644
--- a/mlir/python/mlir/dialects/linalg/opdsl/ops/core_named_ops.py
+++ b/mlir/python/mlir/dialects/linalg/opdsl/ops/core_named_ops.py
@@ -21,162 +21,6 @@ def copy(
     O[None] = cast(U, I[None])
 
 
- at linalg_structured_op
-def exp(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies exp(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.exp(I[None])
-
-
- at linalg_structured_op
-def log(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies log(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.log(I[None])
-
-
- at linalg_structured_op
-def abs(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies abs(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.abs(I[None])
-
-
- at linalg_structured_op
-def ceil(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies ceil(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.ceil(I[None])
-
-
- at linalg_structured_op
-def floor(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies floor(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.floor(I[None])
-
-
- at linalg_structured_op(op_class_name="NegFOp")
-def negf(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies negf(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.negf(I[None])
-
-
- at linalg_structured_op(op_class_name="ReciprocalOp")
-def reciprocal(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies reciprocal(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.reciprocal(I[None])
-
-
- at linalg_structured_op
-def round(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies round(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.round(I[None])
-
-
- at linalg_structured_op
-def sqrt(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies sqrt(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.sqrt(I[None])
-
-
- at linalg_structured_op
-def rsqrt(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies rsqrt(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.rsqrt(I[None])
-
-
- at linalg_structured_op
-def square(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies square(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.square(I[None])
-
-
- at linalg_structured_op
-def tanh(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies tanh(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.tanh(I[None])
-
-
- at linalg_structured_op
-def erf(
-    I=TensorDef(T1),
-    O=TensorDef(T1, output=True),
-):
-    """Applies erf(x) elementwise.
-
-    No numeric casting is performed on the input operand.
-    """
-    O[None] = UnaryFn.erf(I[None])
-
-
 @linalg_structured_op
 def add(
     lhs=TensorDef(T1),
@@ -317,7 +161,7 @@ def powf(
     rhs=TensorDef(T1),
     O=TensorDef(T1, output=True),
 ):
-    """Takes the powf(lhs, rhs) between two inputs, elementwise. For powf(arg, 2) use `linalg.square`.
+    """Takes the powf(lhs, rhs) between two inputs, elementwise. For powf(arg, 2) use `linalg.elementwise kind=square`.
 
     Only applies to floating point values.
 
diff --git a/mlir/test/Dialect/Bufferization/canonicalize.mlir b/mlir/test/Dialect/Bufferization/canonicalize.mlir
index ab3d8df892bc1..887011e5be375 100644
--- a/mlir/test/Dialect/Bufferization/canonicalize.mlir
+++ b/mlir/test/Dialect/Bufferization/canonicalize.mlir
@@ -317,14 +317,14 @@ func.func @tensor_cast_to_buffer_layout_and_memspace(%arg0 : tensor<4x6x16x32xi8
 func.func @load_after_write_from_buffer_cast(%arg0: index, %arg1: index,
                             %arg2: tensor<?x?xf32>) -> f32 {
   %0 = bufferization.to_buffer %arg2 : tensor<?x?xf32> to memref<?x?xf32>
-  linalg.ceil ins(%0 : memref<?x?xf32>) outs(%0 : memref<?x?xf32>)
+  linalg.elementwise kind=#linalg.elementwise_kind<ceil> ins(%0 : memref<?x?xf32>) outs(%0 : memref<?x?xf32>)
   %1 = memref.load %0[%arg0, %arg1] : memref<?x?xf32>
   return %1 : f32
 }
 // CHECK-SAME: %[[IDX0:[0-9a-z]+]]: index, %[[IDX1:[0-9a-z]+]]: index
 // CHECK-SAME: %[[TENSOR:[0-9a-z]+]]: tensor<?x?xf32>
 //      CHECK: %[[M:.+]] = bufferization.to_buffer %[[TENSOR]] : tensor<?x?xf32> to memref<?x?xf32>
-//      CHECK: linalg.ceil ins(%[[M]] : memref<?x?xf32>) outs(%[[M]] : memref<?x?xf32>)
+//      CHECK: linalg.elementwise kind=#linalg.elementwise_kind<ceil> ins(%[[M]] : memref<?x?xf32>) outs(%[[M]] : memref<?x?xf32>)
 //      CHECK: %[[RES:.*]] = memref.load %[[M]][%[[IDX0]], %[[IDX1]]] : memref<?x?xf32>
 //      CHECK: return %[[RES]] : f32
 
diff --git a/mlir/test/Dialect/Linalg/elementwise/named-to-elementwise.mlir b/mlir/test/Dialect/Linalg/elementwise/named-to-elementwise.mlir
index 2332b287ace8d..17276d30efcc8 100644
--- a/mlir/test/Dialect/Linalg/elementwise/named-to-elementwise.mlir
+++ b/mlir/test/Dialect/Linalg/elementwise/named-to-elementwise.mlir
@@ -1,18 +1,5 @@
 // RUN: mlir-opt %s -linalg-morph-ops=named-to-category -split-input-file | FileCheck %s
 
-// CHECK: @exp(%[[A:.+]]: tensor<16x8xf32>, %[[B:.+]]: tensor<16x8xf32>) ->  tensor<16x8xf32> {
-// CHECK: {{.*}} = linalg.elementwise
-// CHECK-SAME:       kind=#linalg.elementwise_kind<exp>
-// CHECK-SAME:       ins(%[[A]] : tensor<16x8xf32>)
-// CHECK-SAME:       outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-//
-func.func @exp(%A : tensor<16x8xf32>, %B : tensor<16x8xf32>) ->  tensor<16x8xf32> {
-  %exp = linalg.exp ins(%A : tensor<16x8xf32>) outs(%B :  tensor<16x8xf32>) -> tensor<16x8xf32>
-  return %exp :  tensor<16x8xf32>
-}
-
-// ----
-
 // CHECK: @add(%[[A:.+]]: tensor<16x8xf32>, %[[B:.+]]: tensor<16x8xf32>, %[[C:.+]]: tensor<16x8xf32>) ->  tensor<16x8xf32> {
 // CHECK: {{.*}} = linalg.elementwise
 // CHECK-SAME:       kind=#linalg.elementwise_kind<add>
diff --git a/mlir/test/Dialect/Linalg/generalize-named-ops.mlir b/mlir/test/Dialect/Linalg/generalize-named-ops.mlir
index 326d7e5400a54..01906302a3468 100644
--- a/mlir/test/Dialect/Linalg/generalize-named-ops.mlir
+++ b/mlir/test/Dialect/Linalg/generalize-named-ops.mlir
@@ -531,281 +531,6 @@ func.func @generalize_divu(%lhs: memref<7x14x21xi32>, %rhs: memref<7x14x21xi32>,
 
 // -----
 
-func.func @generalize_exp(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.exp ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_exp
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[EXP:.+]] = math.exp %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[EXP]] : f32
-
-// -----
-
-func.func @generalize_log(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.log ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_log
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[log:.+]] = math.log %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[log]] : f32
-
-// -----
-
-func.func @generalize_abs(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.abs ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_abs
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[abs:.+]] = math.absf %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[abs]] : f32
-
-// -----
-
-func.func @generalize_ceil(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.ceil ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_ceil
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[ceil:.+]] = math.ceil %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[ceil]] : f32
-
-// -----
-
-func.func @generalize_floor(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.floor ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_floor
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[floor:.+]] = math.floor %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[floor]] : f32
-
-// -----
-
-func.func @generalize_negf(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.negf ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_negf
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[negf:.+]] = arith.negf %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[negf]] : f32
-
-// -----
-
-func.func @generalize_reciprocal(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.reciprocal ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_reciprocal
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: %[[one:.+]] = arith.constant 1.000000e+00 : f32
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[reciprocal:.+]] = arith.divf %[[one]], %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[reciprocal]] : f32
-
-// -----
-
-func.func @generalize_round(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.round ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_round
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[round:.+]] = math.round %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[round]] : f32
-
-// -----
-
-func.func @generalize_sqrt(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.sqrt ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_sqrt
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[sqrt:.+]] = math.sqrt %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[sqrt]] : f32
-
-// -----
-
-func.func @generalize_rsqrt(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.rsqrt ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_rsqrt
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[rsqrt:.+]] = math.rsqrt %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[rsqrt]] : f32
-
-// -----
-
-func.func @generalize_square(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.square ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_square
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[square:.+]] = arith.mulf %[[BBARG0]], %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[square]] : f32
-
-// -----
-
-func.func @generalize_tanh(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.tanh ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_tanh
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[tanh:.+]] = math.tanh %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[tanh]] : f32
-
-// -----
-
-func.func @generalize_erf(%arg: memref<7x14x21xf32>, %out: memref<7x14x21xf32>) {
-  linalg.erf ins(%arg : memref<7x14x21xf32>) outs(%out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_erf
-// CHECK-SAME: (%[[ARG:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME:  ins(%[[LHS]] : memref<7x14x21xf32>) outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK:         ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32)
-// CHECK-NEXT:      %[[erf:.+]] = math.erf %[[BBARG0]] : f32
-// CHECK-NEXT:      linalg.yield %[[erf]] : f32
-
-// -----
-
 func.func @generalize_max(%lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>,
                           %out: memref<7x14x21xf32>) {
   linalg.max ins(%lhs, %rhs : memref<7x14x21xf32>, memref<7x14x21xf32>)
diff --git a/mlir/test/Dialect/Linalg/linalg-morph-category-ops.mlir b/mlir/test/Dialect/Linalg/linalg-morph-category-ops.mlir
deleted file mode 100644
index 246902389bb9e..0000000000000
--- a/mlir/test/Dialect/Linalg/linalg-morph-category-ops.mlir
+++ /dev/null
@@ -1,15 +0,0 @@
-// Forward path `named -> category -> generic`
-// RUN: mlir-opt %s -linalg-morph-ops=named-to-category | FileCheck %s  --check-prefix=NAMED_TO_CATEGORY
-
-// RUN: mlir-opt %s -linalg-morph-ops=named-to-category |  \
-// RUN:   mlir-opt -linalg-morph-ops=category-to-generic | FileCheck %s  --check-prefix=CATEGORY_TO_GENERIC
-
-func.func @exp(%A : tensor<16x8xf32>, %B : tensor<16x8xf32>) ->  tensor<16x8xf32> {
-  %exp = linalg.exp ins(%A : tensor<16x8xf32>) outs(%B :  tensor<16x8xf32>) -> tensor<16x8xf32>
-  return %exp :  tensor<16x8xf32>
-}
-// NAMED_TO_CATEGORY: linalg.elementwise
-// NAMED_TO_CATEGORY-NOT: linalg.exp
-
-// CATEGORY_TO_GENERIC: linalg.generic
-// CATEGORY_TO_GENERIC-NOT: linalg.elementwise
diff --git a/mlir/test/Dialect/Linalg/linalg-morph-elementwise-to-named.mlir b/mlir/test/Dialect/Linalg/linalg-morph-elementwise-to-named.mlir
index 82365f5de8f92..fdf30be6e9e9d 100644
--- a/mlir/test/Dialect/Linalg/linalg-morph-elementwise-to-named.mlir
+++ b/mlir/test/Dialect/Linalg/linalg-morph-elementwise-to-named.mlir
@@ -6,81 +6,6 @@
 // RUN:   mlir-opt -linalg-morph-ops=category-to-named -split-input-file | \
 // RUN:     FileCheck %s
 
-func.func @unary_ops(%A : tensor<16x8xf32>, %B : tensor<16x8xf32>) -> tensor<16x8xf32> {
-  %exp = linalg.elementwise kind=#linalg.elementwise_kind<exp>
-    ins(%A : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %log = linalg.elementwise kind=#linalg.elementwise_kind<log>
-    ins(%exp : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %abs = linalg.elementwise kind=#linalg.elementwise_kind<abs>
-    ins(%log : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %ceil = linalg.elementwise kind=#linalg.elementwise_kind<ceil>
-    ins(%abs : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %floor = linalg.elementwise kind=#linalg.elementwise_kind<floor>
-    ins(%ceil : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %negf = linalg.elementwise kind=#linalg.elementwise_kind<negf>
-    ins(%floor : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %recip = linalg.elementwise kind=#linalg.elementwise_kind<reciprocal>
-    ins(%negf : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %round = linalg.elementwise kind=#linalg.elementwise_kind<round>
-    ins(%recip : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %sqrt = linalg.elementwise kind=#linalg.elementwise_kind<sqrt>
-    ins(%round : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %rsqrt = linalg.elementwise kind=#linalg.elementwise_kind<rsqrt>
-    ins(%sqrt : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %square = linalg.elementwise kind=#linalg.elementwise_kind<square>
-    ins(%rsqrt : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %tanh = linalg.elementwise kind=#linalg.elementwise_kind<tanh>
-    ins(%square : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %erf = linalg.elementwise kind=#linalg.elementwise_kind<erf>
-    ins(%tanh : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  return %erf : tensor<16x8xf32>
-}
-
-// CHECK-LABEL: unary_ops
-// CHECK-SAME: %[[A:.+]]: tensor<16x8xf32>, %[[B:.+]]: tensor<16x8xf32>)
-// CHECK-NOT: linalg.elementwise
-// CHECK: %[[EXP:.+]] = linalg.exp
-// CHECK-SAME: ins(%[[A]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[LOG:.+]] = linalg.log
-// CHECK-SAME: ins(%[[EXP]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[ABS:.+]] = linalg.abs
-// CHECK-SAME: ins(%[[LOG]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[CEIL:.+]] = linalg.ceil
-// CHECK-SAME: ins(%[[ABS]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[FLOOR:.+]] = linalg.floor
-// CHECK-SAME: ins(%[[CEIL]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[NEGF:.+]] = linalg.negf
-// CHECK-SAME: ins(%[[FLOOR]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[RECIP:.+]] = linalg.reciprocal
-// CHECK-SAME: ins(%[[NEGF]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[ROUND:.+]] = linalg.round
-// CHECK-SAME: ins(%[[RECIP]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[SQRT:.+]] = linalg.sqrt
-// CHECK-SAME: ins(%[[ROUND]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[RSQRT:.+]] = linalg.rsqrt
-// CHECK-SAME: ins(%[[SQRT]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[SQUARE:.+]] = linalg.square
-// CHECK-SAME: ins(%[[RSQRT]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: %[[TANH:.+]] = linalg.tanh
-// CHECK-SAME: ins(%[[SQUARE]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-// CHECK: linalg.erf
-// CHECK-SAME: ins(%[[TANH]] : tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[B]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-
-// -----
-
 func.func @binary_ops_int(%A: tensor<?x?xi32>, %B: tensor<?x?xi32>,
                           %Out: tensor<?x?xi32>) -> tensor<?x?xi32> {
   %0 = linalg.elementwise kind=#linalg.elementwise_kind<add>
@@ -210,7 +135,7 @@ func.func @ternary_select(%A: tensor<?x?xi1>, %B: tensor<?x?xf32>,
 // Non-identity indexing maps: should NOT be converted to named op.
 func.func @non_identity_maps(%A: tensor<?xf32>, %Out: tensor<?x?xf32>) -> tensor<?x?xf32> {
   %0 = linalg.elementwise
-    kind=#linalg.elementwise_kind<exp>
+    kind=#linalg.elementwise_kind<abs>
     indexing_maps = [affine_map<(d0, d1) -> (d1)>, affine_map<(d0, d1) -> (d0, d1)>]
     ins(%A : tensor<?xf32>) outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
   return %0 : tensor<?x?xf32>
@@ -218,10 +143,10 @@ func.func @non_identity_maps(%A: tensor<?xf32>, %Out: tensor<?x?xf32>) -> tensor
 
 // CHECK-LABEL: non_identity_maps
 // CHECK-SAME: %[[A:.+]]: tensor<?xf32>, %[[OUT:.+]]: tensor<?x?xf32>)
-// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME: ins(%[[A]] : tensor<?xf32>)
 // CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK-NOT: linalg.exp
+// CHECK-NOT: linalg.abs
 
 // -----
 
diff --git a/mlir/test/Dialect/Linalg/linalg-morph-multi-step.mlir b/mlir/test/Dialect/Linalg/linalg-morph-multi-step.mlir
index 0a0ddbcd85a0a..d7663c04bb213 100644
--- a/mlir/test/Dialect/Linalg/linalg-morph-multi-step.mlir
+++ b/mlir/test/Dialect/Linalg/linalg-morph-multi-step.mlir
@@ -4,57 +4,6 @@
 // RUN:   mlir-opt -linalg-morph-ops=generic-to-named -split-input-file | \
 // RUN:     FileCheck %s  --check-prefix=ALL,ROUND_TRIP
 
-func.func @unary_ops(%A : tensor<16x8xf32>, %B : tensor<16x8xf32>) ->  tensor<16x8xf32> {
-  %exp = linalg.exp ins(%A : tensor<16x8xf32>) outs(%B :  tensor<16x8xf32>) -> tensor<16x8xf32>
-  %log = linalg.log ins(%exp : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %abs = linalg.abs ins(%log : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %ceil = linalg.ceil ins(%abs : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %floor = linalg.floor ins(%ceil : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %negf = linalg.negf ins(%floor : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %recip = linalg.reciprocal ins(%negf : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %round = linalg.round ins(%recip : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %sqrt = linalg.sqrt ins(%round : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %rsqrt = linalg.rsqrt ins(%sqrt : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %square = linalg.square ins(%rsqrt : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %tanh = linalg.tanh ins(%square : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  %erf = linalg.erf ins(%tanh : tensor<16x8xf32>) outs(%B : tensor<16x8xf32>) -> tensor<16x8xf32>
-  return %erf :  tensor<16x8xf32>
-}
-
-// ALL-LABEL: unary_ops
-
-// NAMED_TO_GENERIC-COUNT-13: linalg.generic
-// NAMED_TO_GENERIC-NOT: linalg.exp
-// NAMED_TO_GENERIC-NOT: linalg.log
-// NAMED_TO_GENERIC-NOT: linalg.abs
-// NAMED_TO_GENERIC-NOT: linalg.ceil
-// NAMED_TO_GENERIC-NOT: linalg.floor
-// NAMED_TO_GENERIC-NOT: linalg.negf
-// NAMED_TO_GENERIC-NOT: linalg.reciprocal
-// NAMED_TO_GENERIC-NOT: linalg.round
-// NAMED_TO_GENERIC-NOT: linalg.sqrt
-// NAMED_TO_GENERIC-NOT: linalg.rsqrt
-// NAMED_TO_GENERIC-NOT: linalg.square
-// NAMED_TO_GENERIC-NOT: linalg.tanh
-// NAMED_TO_GENERIC-NOT: linalg.erf
-
-// ROUND_TRIP: linalg.exp
-// ROUND_TRIP: linalg.log
-// ROUND_TRIP: linalg.abs
-// ROUND_TRIP: linalg.ceil
-// ROUND_TRIP: linalg.floor
-// ROUND_TRIP: linalg.negf
-// ROUND_TRIP: linalg.reciprocal
-// ROUND_TRIP: linalg.round
-// ROUND_TRIP: linalg.sqrt
-// ROUND_TRIP: linalg.rsqrt
-// ROUND_TRIP: linalg.square
-// ROUND_TRIP: linalg.tanh
-// ROUND_TRIP: linalg.erf
-// ROUND_TRIP-NOT: linalg.generic
-
-// -----
-
 func.func @binary_ops_int(%A: tensor<?x?xi32>, %B: tensor<?x?xi32>,
                           %Out: tensor<?x?xi32>) -> tensor<?x?xi32> {
   %0 = linalg.add ins(%A, %B : tensor<?x?xi32>, tensor<?x?xi32>)
diff --git a/mlir/test/Dialect/Linalg/match-ops-interpreter.mlir b/mlir/test/Dialect/Linalg/match-ops-interpreter.mlir
index 5b58a9464a76f..e8333fb5122be 100644
--- a/mlir/test/Dialect/Linalg/match-ops-interpreter.mlir
+++ b/mlir/test/Dialect/Linalg/match-ops-interpreter.mlir
@@ -842,15 +842,15 @@ module attributes { transform.with_named_sequence } {
     // expected-remark @below {{op result}}
     // expected-note @below {{value handle points to an op result #0}}
     // expected-remark @below {{single user}}
-    linalg.negf ins(%2 : tensor<42x42xf32>) outs(%0 : tensor<42x42xf32>) -> tensor<42x42xf32>
+    linalg.elementwise kind=#linalg.elementwise_kind<negf> ins(%2 : tensor<42x42xf32>) outs(%0 : tensor<42x42xf32>) -> tensor<42x42xf32>
     // expected-remark @below {{matched result value}}
     // expected-remark @below {{op result}}
     // expected-note @below {{value handle points to an op result #0}}
-    linalg.exp ins(%3 : tensor<42x42xf32>) outs(%0 : tensor<42x42xf32>) -> tensor<42x42xf32>
+    linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%3 : tensor<42x42xf32>) outs(%0 : tensor<42x42xf32>) -> tensor<42x42xf32>
     // expected-remark @below {{matched result value}}
     // expected-remark @below {{op result}}
     // expected-note @below {{value handle points to an op result #0}}
-    linalg.exp ins(%3 : tensor<42x42xf32>) outs(%0 : tensor<42x42xf32>) -> tensor<42x42xf32>
+    linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%3 : tensor<42x42xf32>) outs(%0 : tensor<42x42xf32>) -> tensor<42x42xf32>
     return
   }
 }
diff --git a/mlir/test/Dialect/Linalg/named-ops-fail.mlir b/mlir/test/Dialect/Linalg/named-ops-fail.mlir
index bf9c1b705f157..cd7e3498b9b0e 100644
--- a/mlir/test/Dialect/Linalg/named-ops-fail.mlir
+++ b/mlir/test/Dialect/Linalg/named-ops-fail.mlir
@@ -80,214 +80,6 @@ func.func @divu_broadcast(%arg0: memref<8x16xi32>, %arg1: memref<4x8x16xi32>, %a
 
 // -----
 
-func.func @exp_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.exp ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @exp_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.exp ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @log_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.log ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @log_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.log ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @abs_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.abs ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @abs_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.abs ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @ceil_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.ceil ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @ceil_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.ceil ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @floor_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.floor ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @floor_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.floor ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @negf_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.negf ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @negf_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.negf ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @reciprocal_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.reciprocal ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @reciprocal_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.reciprocal ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @round_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.round ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @round_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.round ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @sqrt_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.sqrt ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @sqrt_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.sqrt ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @rsqrt_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.rsqrt ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @rsqrt_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.rsqrt ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @square_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.square ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @square_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.square ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @tanh_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.tanh ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @tanh_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.tanh ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @erf_type_cast(%arg: memref<4x8x16xf16>, %out: memref<4x8x16xf32>) {
-  // CHECK: operand 1 ('f16') doesn't match the element type of the enclosing linalg.generic op ('f32')
-  linalg.erf ins(%arg : memref<4x8x16xf16>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-func.func @erf_broadcast(%arg: memref<8x16xf32>, %out: memref<4x8x16xf32>) {
-  // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
-  linalg.erf ins(%arg : memref<8x16xf32>) outs(%out: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
 func.func @max_type_cast(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf16>, %arg2: memref<4x8x16xf32>) {
   // CHECK: op requires the same type for all operands and results
   linalg.max ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf16>) outs(%arg2: memref<4x8x16xf32>)
diff --git a/mlir/test/Dialect/Linalg/named-ops.mlir b/mlir/test/Dialect/Linalg/named-ops.mlir
index b9cb8e012e651..61aabdb663c6a 100644
--- a/mlir/test/Dialect/Linalg/named-ops.mlir
+++ b/mlir/test/Dialect/Linalg/named-ops.mlir
@@ -2332,409 +2332,6 @@ func.func @div_unsigned_tensor(%arg0: tensor<4x8x16xi32>, %arg1: tensor<4x8x16xi
 
 // -----
 
-// CHECK-LABEL: func @exp_dynamic
-func.func @exp_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.exp
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.exp ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @exp_static
-func.func @exp_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.exp
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.exp ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @exp_tensor
-func.func @exp_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.exp
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.exp ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @log_dynamic
-func.func @log_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.log
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.log ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @log_static
-func.func @log_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.log
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.log ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @log_tensor
-func.func @log_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.log
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.log ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @abs_dynamic
-func.func @abs_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.abs
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.abs ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @abs_static
-func.func @abs_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.abs
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.abs ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @abs_tensor
-func.func @abs_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.abs
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.abs ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @ceil_dynamic
-func.func @ceil_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.ceil
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.ceil ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @ceil_static
-func.func @ceil_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.ceil
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.ceil ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @ceil_tensor
-func.func @ceil_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.ceil
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.ceil ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @floor_dynamic
-func.func @floor_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.floor
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.floor ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @floor_static
-func.func @floor_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.floor
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.floor ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @floor_tensor
-func.func @floor_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.floor
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.floor ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @negf_dynamic
-func.func @negf_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.negf
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.negf ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @negf_static
-func.func @negf_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.negf
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.negf ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @negf_tensor
-func.func @negf_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.negf
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.negf ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @reciprocal_dynamic
-func.func @reciprocal_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.reciprocal
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.reciprocal ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @reciprocal_static
-func.func @reciprocal_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.reciprocal
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.reciprocal ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @reciprocal_tensor
-func.func @reciprocal_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.reciprocal
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.reciprocal ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @round_dynamic
-func.func @round_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.round
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.round ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @round_static
-func.func @round_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.round
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.round ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @round_tensor
-func.func @round_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.round
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.round ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @sqrt_dynamic
-func.func @sqrt_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.sqrt
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.sqrt ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @sqrt_static
-func.func @sqrt_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.sqrt
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.sqrt ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @sqrt_tensor
-func.func @sqrt_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.sqrt
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.sqrt ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @rsqrt_dynamic
-func.func @rsqrt_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.rsqrt
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.rsqrt ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @rsqrt_static
-func.func @rsqrt_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.rsqrt
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.rsqrt ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @rsqrt_tensor
-func.func @rsqrt_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.rsqrt
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.rsqrt ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @square_dynamic
-func.func @square_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.square
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.square ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @square_static
-func.func @square_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.square
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.square ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @square_tensor
-func.func @square_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.square
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.square ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @tanh_dynamic
-func.func @tanh_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.tanh
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.tanh ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @tanh_static
-func.func @tanh_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.tanh
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.tanh ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @tanh_tensor
-func.func @tanh_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.tanh
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.tanh ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @erf_dynamic
-func.func @erf_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>) {
-  // CHECK: linalg.erf
-  // CHECK-SAME: ins(%{{.+}} : memref<?x?x?xf32>) outs(%{{.+}} : memref<?x?x?xf32>)
-  linalg.erf ins(%arg0 : memref<?x?x?xf32>) outs(%arg1: memref<?x?x?xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @erf_static
-func.func @erf_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>) {
-  // CHECK: linalg.erf
-  // CHECK-SAME: ins(%{{.+}} : memref<4x8x16xf32>) outs(%{{.+}} : memref<4x8x16xf32>)
-  linalg.erf ins(%arg0 : memref<4x8x16xf32>) outs(%arg1: memref<4x8x16xf32>)
-  return
-}
-
-// -----
-
-// CHECK-LABEL: func @erf_tensor
-func.func @erf_tensor(%arg0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
-  %0 = tensor.empty() : tensor<4x8x16xf32>
-  // CHECK: linalg.erf
-  // CHECK-SAME: ins(%{{.+}} : tensor<4x8x16xf32>) outs(%{{.+}} : tensor<4x8x16xf32>)
-  %1 = linalg.erf ins(%arg0 : tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
-  return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
 // CHECK-LABEL: func @max_dynamic
 func.func @max_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>, %arg2: memref<?x?x?xf32>) {
   // CHECK: linalg.max
diff --git a/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-category-ops.mlir b/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-category-ops.mlir
index b9d7db6227816..fb234825d187c 100644
--- a/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-category-ops.mlir
+++ b/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-category-ops.mlir
@@ -6,8 +6,6 @@
 // RUN: | FileCheck %s
 
 func.func @unary_ops(%A: memref<7x14x21xf32>, %Out: memref<7x14x21xf32>) {
-  linalg.elementwise kind=#linalg.elementwise_kind<exp>
-    ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
   linalg.elementwise kind=#linalg.elementwise_kind<log>
     ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
   linalg.elementwise kind=#linalg.elementwise_kind<abs>
@@ -61,10 +59,6 @@ func.func @unary_ops(%A: memref<7x14x21xf32>, %Out: memref<7x14x21xf32>) {
 
 // CHECK-LABEL: unary_ops
 // CHECK-SAME: %[[A:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-// CHECK-NOT: linalg.generic
-// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
 // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<log>
 // CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
 // CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
diff --git a/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-named-ops.mlir b/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-named-ops.mlir
index 3ea6f99827484..0edf9d7bb7ded 100644
--- a/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-named-ops.mlir
+++ b/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-named-ops.mlir
@@ -5,68 +5,6 @@
 // RUN: | mlir-opt -split-input-file -linalg-morph-ops=generic-to-named \
 // RUN: | FileCheck %s
 
-func.func @unary_ops(%A: memref<7x14x21xf32>, %Out: memref<7x14x21xf32>) {
-  linalg.exp ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.log ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.abs ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.ceil ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.floor ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.negf ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.reciprocal ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.round ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.sqrt ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.rsqrt ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.square ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.tanh ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  linalg.erf ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
-  return
-}
-
-// CHECK-LABEL: unary_ops
-// CHECK-SAME: %[[A:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
-// CHECK-NOT: linalg.generic
-// CHECK: linalg.exp
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.log
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.abs
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.ceil
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.floor
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.negf
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.reciprocal
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.round
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.sqrt
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.rsqrt
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.square
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.tanh
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-// CHECK: linalg.erf
-// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// -----
-              
 func.func @binary_ops_int(%A: memref<10xi32>, %B: memref<10xi32>,
                           %Out: memref<10xi32>) {
   linalg.add ins(%A, %B : memref<10xi32>, memref<10xi32>) outs(%Out : memref<10xi32>)
diff --git a/mlir/test/Dialect/Linalg/scalable-unpack-producer-fusion.mlir b/mlir/test/Dialect/Linalg/scalable-unpack-producer-fusion.mlir
index 96dc4937176fc..1bbc5add1f83b 100644
--- a/mlir/test/Dialect/Linalg/scalable-unpack-producer-fusion.mlir
+++ b/mlir/test/Dialect/Linalg/scalable-unpack-producer-fusion.mlir
@@ -26,7 +26,7 @@ func.func @unpack_elemwise_scalable(%arg0: tensor<4x8x?x?xf32>, %arg1: tensor<?x
   %1 = linalg.unpack %arg0 inner_dims_pos = [0, 1]
       inner_tiles = [%c8_vscale, %c4_vscale] into %0
       : tensor<4x8x?x?xf32> -> tensor<?x?xf32>
-  %2 = linalg.exp ins(%1: tensor<?x?xf32>)
+  %2 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%1: tensor<?x?xf32>)
                        outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
   return %2 : tensor<?x?xf32>
 }
@@ -36,7 +36,7 @@ module attributes {transform.with_named_sequence} {
   // the inner tiles, asserted via `Multiple`. The outer dims become
   // `ceilDiv(loop tile, inner tile)`.
   transform.named_sequence @aligned(%arg1: !transform.any_op {transform.readonly}) {
-    %exp = transform.structured.match ops{["linalg.exp"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+    %exp = transform.structured.match ops{["linalg.elementwise"]} in %arg1 : (!transform.any_op) -> !transform.any_op
     %mulis = transform.structured.match ops{["arith.muli"]} in %arg1 : (!transform.any_op) -> !transform.any_op
     %h8, %h4, %h16 = transform.split_handle %mulis : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
     %tiled, %loops:2 = transform.structured.fuse %exp tile_sizes [%h16, %h8] interchange [0, 1]
@@ -60,7 +60,7 @@ module attributes {transform.with_named_sequence} {
   //       ALIGNED:        %[[UNPACK:.*]] = linalg.unpack %[[SRC]]
   //  ALIGNED-SAME:            tensor<?x?x?x?xf32> -> tensor<?x?xf32>
   //   ALIGNED-NOT:         tensor.extract_slice %[[UNPACK]]
-  //       ALIGNED:        linalg.exp ins(%[[UNPACK]]
+  //       ALIGNED:        linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[UNPACK]]
   //       ALIGNED:      scf.yield
   //       ALIGNED:    scf.yield
   //       ALIGNED:    return %[[RES]]
@@ -68,7 +68,7 @@ module attributes {transform.with_named_sequence} {
   // Equal: loop tile sizes (8 * vscale, 4 * vscale) equal the inner tiles,
   // asserted via `Equal`; the fused unpack's outer dims collapse to 1.
   transform.named_sequence @equal(%arg1: !transform.any_op {transform.readonly}) {
-    %exp = transform.structured.match ops{["linalg.exp"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+    %exp = transform.structured.match ops{["linalg.elementwise"]} in %arg1 : (!transform.any_op) -> !transform.any_op
     %mulis = transform.structured.match ops{["arith.muli"]} in %arg1 : (!transform.any_op) -> !transform.any_op
     %h8, %h4, %h16 = transform.split_handle %mulis : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
     %tiled, %loops:2 = transform.structured.fuse %exp tile_sizes [%h8, %h4] interchange [0, 1]
@@ -87,7 +87,7 @@ module attributes {transform.with_named_sequence} {
   //       EQUAL:        %[[UNPACK:.*]] = linalg.unpack
   //  EQUAL-SAME:            tensor<1x1x?x?xf32> -> tensor<?x?xf32>
   //   EQUAL-NOT:         tensor.extract_slice %[[UNPACK]]
-  //       EQUAL:        linalg.exp ins(%[[UNPACK]]
+  //       EQUAL:        linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[UNPACK]]
   //       EQUAL:      scf.yield
   //       EQUAL:    scf.yield
   //       EQUAL:    return %[[RES]]
@@ -96,7 +96,7 @@ module attributes {transform.with_named_sequence} {
   // tiles and no hint is passed, so the fused unpack over-computes and a trailing
   // extract_slice recovers the needed slice.
   transform.named_sequence @unaligned(%arg1: !transform.any_op {transform.readonly}) {
-    %exp = transform.structured.match ops{["linalg.exp"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+    %exp = transform.structured.match ops{["linalg.elementwise"]} in %arg1 : (!transform.any_op) -> !transform.any_op
     %tiled, %loops:2 = transform.structured.fuse %exp tile_sizes [7, 5] interchange [0, 1]
       : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
     transform.yield
@@ -109,8 +109,8 @@ module attributes {transform.with_named_sequence} {
   //       UNALIGNED:        %[[UNPACK:.*]] = linalg.unpack
   //  UNALIGNED-SAME:            tensor<?x?x?x?xf32> -> tensor<?x?xf32>
   //       UNALIGNED:        %[[EXTRACT:.*]] = tensor.extract_slice %[[UNPACK]]
-  //   UNALIGNED-NOT:        linalg.exp ins(%[[UNPACK]]
-  //       UNALIGNED:        linalg.exp ins(%[[EXTRACT]]
+  //   UNALIGNED-NOT:        linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[UNPACK]]
+  //       UNALIGNED:        linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[EXTRACT]]
   //       UNALIGNED:      scf.yield
   //       UNALIGNED:    scf.yield
   //       UNALIGNED:    return %[[RES]]
@@ -151,7 +151,7 @@ func.func @fuse_unpack_into_containing(
         : tensor<?x?xf32> to tensor<?x?xf32>
     %oslice = tensor.extract_slice %o[%i, %j] [%c8_vscale_step, %c4_vscale_step] [1, 1]
         : tensor<?x?xf32> to tensor<?x?xf32>
-    %0 = linalg.exp ins(%slice : tensor<?x?xf32>) outs(%oslice : tensor<?x?xf32>) -> tensor<?x?xf32>
+    %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%slice : tensor<?x?xf32>) outs(%oslice : tensor<?x?xf32>) -> tensor<?x?xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %0 into %o[%i, %j] [%c8_vscale_step, %c4_vscale_step] [1, 1]
           : tensor<?x?xf32> into tensor<?x?xf32>
@@ -175,7 +175,7 @@ module attributes {transform.with_named_sequence} {
   //       EQUAL:     %[[UNPACK:.+]] = linalg.unpack
   //  EQUAL-SAME:         : tensor<1x1x?x?xf32> -> tensor<?x?xf32>
   //   EQUAL-NOT:     tensor.extract_slice %[[UNPACK]]
-  //       EQUAL:     linalg.exp ins(%[[UNPACK]]
+  //       EQUAL:     linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[UNPACK]]
 
   // No hint: general (unaligned) tiling with a trailing result slice.
   transform.named_sequence @unaligned(%arg1: !transform.any_op {transform.readonly}) {
@@ -190,8 +190,8 @@ module attributes {transform.with_named_sequence} {
   //     UNALIGNED:     %[[UNPACK:.+]] = linalg.unpack
   // UNALIGNED-SAME:         : tensor<?x?x?x?xf32> -> tensor<?x?xf32>
   //     UNALIGNED:     %[[EXTRACTED:.+]] = tensor.extract_slice %[[UNPACK]]
-  // UNALIGNED-NOT:     linalg.exp ins(%[[UNPACK]]
-  //     UNALIGNED:     linalg.exp ins(%[[EXTRACTED]]
+  // UNALIGNED-NOT:     linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[UNPACK]]
+  //     UNALIGNED:     linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[EXTRACTED]]
 
   // Aligned: the `Multiple` hints assert the containing loop's tile sizes are
   // multiples of the inner tiles. Although the loop tile size and inner tile sizes
@@ -214,7 +214,7 @@ module attributes {transform.with_named_sequence} {
   //       ALIGNED:     %[[UNPACK:.+]] = linalg.unpack
   //  ALIGNED-SAME:         : tensor<?x?x?x?xf32> -> tensor<?x?xf32>
   //   ALIGNED-NOT:     tensor.extract_slice %[[UNPACK]]
-  //       ALIGNED:     linalg.exp ins(%[[UNPACK]]
+  //       ALIGNED:     linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[UNPACK]]
 
   // Dummy entry point so the default RUN line resolves here.
   transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
@@ -324,7 +324,7 @@ func.func @fuse_unpack_through_block_arg(
       shared_outs(%o = %unpack) -> (tensor<?x?xf32>) {
     %slice = tensor.extract_slice %o[%i, %j] [%c8_vscale, %c4_vscale] [1, 1]
         : tensor<?x?xf32> to tensor<?x?xf32>
-    %0 = linalg.exp ins(%slice : tensor<?x?xf32>) outs(%slice : tensor<?x?xf32>) -> tensor<?x?xf32>
+    %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%slice : tensor<?x?xf32>) outs(%slice : tensor<?x?xf32>) -> tensor<?x?xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %0 into %o[%i, %j] [%c8_vscale, %c4_vscale] [1, 1]
           : tensor<?x?xf32> into tensor<?x?xf32>
@@ -337,7 +337,7 @@ func.func @fuse_unpack_through_block_arg(
 //       CHECK:     %[[UNPACK:.+]] = linalg.unpack
 //  CHECK-SAME:         : tensor<1x1x?x?xf32> -> tensor<?x?xf32>
 //   CHECK-NOT:     tensor.extract_slice %[[UNPACK]]
-//       CHECK:     linalg.exp ins(%[[UNPACK]]
+//       CHECK:     linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[UNPACK]]
 
 module attributes {transform.with_named_sequence} {
   // The `Equal` hints assert the containing loop's tile sizes equal the unpack
diff --git a/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir b/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir
index 31b1943967282..2961de3a8d945 100644
--- a/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir
+++ b/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir
@@ -6,39 +6,9 @@
 
 #umap = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
 func.func @unary_ops(%A: tensor<?x?x?xf32>, %Out: tensor<?x?x?xf32>) -> tensor<?x?x?xf32> {
-  %0 = linalg.generic
-    {indexing_maps = [#umap, #umap],
-    iterator_types = ["parallel", "parallel","parallel"]}
-    ins(%A : tensor<?x?x?xf32>)
-    outs(%Out : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.exp %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %1 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%0 : tensor<?x?x?xf32>) outs(%Out : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.log %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %2 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%1 : tensor<?x?x?xf32>) outs(%Out : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.absf %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %3 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%2 : tensor<?x?x?xf32>) outs(%Out : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.ceil %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
   %4 = linalg.generic
           {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%3 : tensor<?x?x?xf32>) outs(%Out : tensor<?x?x?xf32>) {
+          ins(%A : tensor<?x?x?xf32>) outs(%Out : tensor<?x?x?xf32>) {
   ^bb0(%in: f32, %out: f32):
     %v = math.floor %in : f32
     linalg.yield %v : f32
@@ -190,61 +160,12 @@ func.func @unary_ops(%A: tensor<?x?x?xf32>, %Out: tensor<?x?x?xf32>) -> tensor<?
 // ALL-LABEL: unary_ops
 // ALL-SAME: %[[A:.+]]: tensor<?x?x?xf32>, %[[OUT:.+]]: tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
 
-// NAMED-NOT: linalg.generic
-// NAMED: %[[RES0:.+]] = linalg.exp
-// NAMED-SAME: ins(%[[A]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES1:.+]] = linalg.log
-// NAMED-SAME: ins(%[[RES0]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES2:.+]] = linalg.abs
-// NAMED-SAME: ins(%[[RES1]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES3:.+]] = linalg.ceil
-// NAMED-SAME: ins(%[[RES2]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES4:.+]] = linalg.floor
-// NAMED-SAME: ins(%[[RES3]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES5:.+]] = linalg.negf
-// NAMED-SAME: ins(%[[RES4]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES6:.+]] = linalg.reciprocal
-// NAMED-SAME: ins(%[[RES5]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES7:.+]] = linalg.round
-// NAMED-SAME: ins(%[[RES6]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES8:.+]] = linalg.sqrt
-// NAMED-SAME: ins(%[[RES7]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES9:.+]] = linalg.rsqrt
-// NAMED-SAME: ins(%[[RES8]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES10:.+]] = linalg.square
-// NAMED-SAME: ins(%[[RES9]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES11:.+]] = linalg.tanh
-// NAMED-SAME: ins(%[[RES10]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// NAMED: %[[RES12:.+]] = linalg.erf
-// NAMED-SAME: ins(%[[RES11]] : tensor<?x?x?xf32>)
-// NAMED-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-
-// CATEGORY: %[[RES0:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
-// CATEGORY-SAME: ins(%[[A]] : tensor<?x?x?xf32>)
-// CATEGORY-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CATEGORY: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<log>
-// CATEGORY-SAME: ins(%[[RES0]] : tensor<?x?x?xf32>)
-// CATEGORY-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CATEGORY: %[[RES2:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
-// CATEGORY-SAME: ins(%[[RES1]] : tensor<?x?x?xf32>)
-// CATEGORY-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CATEGORY: %[[RES3:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<ceil>
-// CATEGORY-SAME: ins(%[[RES2]] : tensor<?x?x?xf32>)
-// CATEGORY-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
+// No unary linalg named ops remain, so generic-to-named leaves them as generics.
+// NAMED-NOT: linalg.elementwise
+// NAMED: linalg.generic
+
 // CATEGORY: %[[RES4:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<floor>
-// CATEGORY-SAME: ins(%[[RES3]] : tensor<?x?x?xf32>)
+// CATEGORY-SAME: ins(%[[A]] : tensor<?x?x?xf32>)
 // CATEGORY-SAME: outs(%[[OUT]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
 // CATEGORY: %[[RES5:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<negf>
 // CATEGORY-SAME: ins(%[[RES4]] : tensor<?x?x?xf32>)
@@ -316,7 +237,7 @@ func.func @unary_ops_non_identity(%A: tensor<?xf32>, %Out: tensor<?x?xf32>) -> t
     ins(%A : tensor<?xf32>)
     outs(%Out : tensor<?x?xf32>) {
   ^bb0(%in: f32, %out: f32):  
-    %v = math.exp %in : f32
+    %v = math.absf %in : f32
     linalg.yield %v : f32
   } -> tensor<?x?xf32>
   return %0 : tensor<?x?xf32>
@@ -329,11 +250,11 @@ func.func @unary_ops_non_identity(%A: tensor<?xf32>, %Out: tensor<?x?xf32>) -> t
 // ALL-SAME: %[[A:.+]]: tensor<?xf32>, %[[OUT:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
 
 // Named ops cannot carry user-defined indexing maps -> expect no change.
-// NAMED-NOT: linalg.exp
+// NAMED-NOT: linalg.abs
 // NAMED: linalg.generic
 
 // CATEGORY-NOT: linalg.generic
-// CATEGORY: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+// CATEGORY: linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CATEGORY-SAME: indexing_maps = [#[[MAP_BC]], #[[MAP_TP]]]
 // CATEGORY-SAME: ins(%[[A]] : tensor<?xf32>)
 // CATEGORY-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
diff --git a/mlir/test/Dialect/Linalg/transform-op-fuse-into-containing.mlir b/mlir/test/Dialect/Linalg/transform-op-fuse-into-containing.mlir
index ab38f9f2f5943..f7019e79ca73c 100644
--- a/mlir/test/Dialect/Linalg/transform-op-fuse-into-containing.mlir
+++ b/mlir/test/Dialect/Linalg/transform-op-fuse-into-containing.mlir
@@ -26,8 +26,8 @@ module {
       // CHECK: %[[T1:.*]] = linalg.fill {{.*}} outs(%[[T0]]
       %6 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[T1]]
-      %7 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[T1]]
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
       }
@@ -76,8 +76,8 @@ module {
       %4 = affine.min #map2(%arg3)[%arg0]
       %5 = tensor.extract_slice %o[%3] [%4] [1] : tensor<64xf32> to tensor<?xf32>
 
-      // CHECK: %[[T2:.*]] = linalg.exp ins(%[[INIT_TENSOR]]
-      %7 = linalg.exp ins(%0 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[INIT_TENSOR]]
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%0 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<64xf32>
       }
@@ -177,8 +177,8 @@ module {
       // CHECK: %[[T1:.*]] = linalg.fill {{.*}} outs(%[[T0]]
       %6 = tensor.extract_slice %arg1[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      // CHECK: %[[T2:.*]] = linalg.exp {{.*}} outs(%[[T1]]
-      %7 = linalg.exp ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> {{.*}} outs(%[[T1]]
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
       }
@@ -228,8 +228,8 @@ module {
       // CHECK: %[[T2:.*]] = linalg.fill {{.*}} outs(%[[T1]]
       %6 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      // CHECK: %[[T3:.*]] = linalg.exp ins(%[[T2]] : tensor<?xf32>) outs(%[[T0]] : tensor<?xf32>)
-      %7 = linalg.exp ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      // CHECK: %[[T3:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[T2]] : tensor<?xf32>) outs(%[[T0]] : tensor<?xf32>)
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
       }
@@ -308,10 +308,10 @@ module {
           // CHECK:  %[[EX1:.*]] = tensor.extract_slice %[[BBARG2]]{{.*}}: tensor<?x?x?xf32> to tensor<1x1x1xf32>
           // CHECK:  linalg.elementwise kind=#linalg.elementwise_kind<abs> ins({{.*}} : tensor<1x1x1xf32>) outs(%[[EX1]] : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
           // CHECK:  %[[EX2:.*]] = tensor.extract_slice %[[BBARG2]]{{.*}} : tensor<?x?x?xf32> to tensor<1x1x1xf32>
-          // CHECK:  linalg.elementwise kind=#linalg.elementwise_kind<exp> ins({{.*}} : tensor<1x1x1xf32>) outs(%[[EX2]] : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
+          // CHECK:  linalg.elementwise kind=#linalg.elementwise_kind<abs> ins({{.*}} : tensor<1x1x1xf32>) outs(%[[EX2]] : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
           %extracted_slice = tensor.extract_slice %0[%arg2, %arg4, %arg6] [1, 1, 1] [1, 1, 1] : tensor<?x?x?xf32> to tensor<1x1x1xf32>
           %extracted_slice_2 = tensor.extract_slice %arg7[%arg2, %arg4, %arg6] [1, 1, 1] [1, 1, 1] : tensor<?x?x?xf32> to tensor<1x1x1xf32>
-          %4 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%extracted_slice : tensor<1x1x1xf32>) outs(%extracted_slice_2 : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
+          %4 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%extracted_slice : tensor<1x1x1xf32>) outs(%extracted_slice_2 : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
           %inserted_slice = tensor.insert_slice %4 into %arg7[%arg2, %arg4, %arg6] [1, 1, 1] [1, 1, 1] : tensor<1x1x1xf32> into tensor<?x?x?xf32>
           scf.yield %inserted_slice : tensor<?x?x?xf32>
         }
@@ -374,8 +374,8 @@ module {
       // CHECK: %[[T1:.*]]:2 = linalg.generic {{.*}} ins(%[[T0]]
       %6 = tensor.extract_slice %0#0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      // CHECK: %[[T2:.*]] = linalg.exp ins(%[[T1]]#0
-      %7 = linalg.exp ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[T1]]#0
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
       }
@@ -410,8 +410,8 @@ module {
       %2 = tensor.extract_slice %0[%i][1][1] : tensor<2xf32> to tensor<1xf32>
       %3 = tensor.extract_slice %arg1[%i][1][1] : tensor<2xf32> to tensor<1xf32>
       // CHECK: %[[FUSED:.+]] = linalg.fill
-      // CHECK: exp ins(%[[FUSED]]
-      %4 = linalg.exp ins(%2 : tensor<1xf32>) outs(%3 : tensor<1xf32>) -> tensor<1xf32>
+      // CHECK: elementwise kind=#linalg.elementwise_kind<abs> ins(%[[FUSED]]
+      %4 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%2 : tensor<1xf32>) outs(%3 : tensor<1xf32>) -> tensor<1xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %4 into %arg1[%i][1][1] : tensor<1xf32> into tensor<2xf32>
       }
@@ -480,7 +480,7 @@ module {
       // CHECK: %[[T1:.*]]:2 = linalg.generic {{.*}}
       %6 = tensor.extract_slice %0#0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      %7 = linalg.exp ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         // CHECK: tensor.parallel_insert_slice %[[T1]]#0 into %[[ARG7]][%[[I0]]] [%[[I1]]] [1] : tensor<?xf32> into tensor<?xf32>
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
@@ -549,7 +549,7 @@ module {
       // CHECK: %[[T1:.*]] = linalg.generic {{.*}}
       %6 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      %7 = linalg.exp ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         // CHECK: tensor.parallel_insert_slice %[[T1]] into %[[ARG7]][%[[I0]]] [%[[I1]]] [1] : tensor<?xf32> into tensor<?xf32>
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
@@ -616,7 +616,7 @@ module {
       // CHECK: %[[T1:.*]] = linalg.generic {{.*}}
       %6 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      %7 = linalg.exp ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         // CHECK: tensor.parallel_insert_slice %[[T1]] into %[[ARG7]][%[[I0]]] [%[[I1]]] [1] : tensor<?xf32> into tensor<?xf32>
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
@@ -692,7 +692,7 @@ module {
       // CHECK: %[[T2:.*]] = linalg.generic {{.*}}
       %7 = tensor.extract_slice %1[%4] [%5] [1] : tensor<?xf32> to tensor<?xf32>
 
-      %8 = linalg.exp ins(%7 : tensor<?xf32>) outs(%6 : tensor<?xf32>) -> tensor<?xf32>
+      %8 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%7 : tensor<?xf32>) outs(%6 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         // CHECK: tensor.parallel_insert_slice %[[T2]] into %[[ARG7]][%[[I0]]] [%[[I1]]] [1] : tensor<?xf32> into tensor<?xf32>
         tensor.parallel_insert_slice %8 into %o[%2] [%5] [1] : tensor<?xf32> into tensor<?xf32>
diff --git a/mlir/test/Dialect/Linalg/transform-op-fuse.mlir b/mlir/test/Dialect/Linalg/transform-op-fuse.mlir
index aa1bbd8db72ff..5dffd4070b49c 100644
--- a/mlir/test/Dialect/Linalg/transform-op-fuse.mlir
+++ b/mlir/test/Dialect/Linalg/transform-op-fuse.mlir
@@ -5,10 +5,10 @@ func.func @fuse_unary(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<
 
   //     CHECK: %[[RES:.*]] = scf.for
   //     CHECK:    scf.for
-  //     CHECK:       linalg.exp
+  //     CHECK:       linalg.elementwise
   //     CHECK:       linalg.add
   //     CHECK: return %[[RES]]
-  %0 = linalg.exp ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
   %1 = linalg.add ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
@@ -31,14 +31,14 @@ func.func @fuse_unary(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<
 
   //     CHECK: %[[PARTIAL_RES:.*]] = scf.for
   //     CHECK:     scf.for
-  //     CHECK:       linalg.exp
+  //     CHECK:       linalg.elementwise
   //     CHECK:       linalg.add
   //     CHECK: %[[RES:.*]] = scf.for {{.*}}%[[PARTIAL_RES]]
   //     CHECK:     scf.for
-  //     CHECK:       linalg.exp
+  //     CHECK:       linalg.elementwise
   //     CHECK:       linalg.add
   //     CHECK: return %[[RES]]
-  %0 = linalg.exp ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
   %1 = linalg.add ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
@@ -62,10 +62,10 @@ func.func @fuse_unary_param(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> t
 
   //     CHECK: %[[RES:.*]] = scf.for
   //     CHECK:    scf.for
-  //     CHECK:       linalg.exp
+  //     CHECK:       linalg.elementwise
   //     CHECK:       linalg.add
   //     CHECK: return %[[RES]]
-  %0 = linalg.exp ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
   %1 = linalg.add ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
@@ -91,10 +91,10 @@ module attributes {transform.with_named_sequence} {
 func.func @fuse_unary_forall(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<?x?xf32> {
 
   //     CHECK: %[[RES:.*]] = scf.forall
-  //     CHECK:       linalg.exp
+  //     CHECK:       linalg.elementwise
   //     CHECK:       linalg.add
   //     CHECK: return %[[RES]]
-  %0 = linalg.exp ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
   %1 = linalg.add ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
@@ -117,10 +117,10 @@ func.func @fuse_unary_packed_tile_sizes(%arg0: tensor<?x?xf32>, %arg1: tensor<?x
 
   //     CHECK: %[[RES:.*]] = scf.for
   //     CHECK:    scf.for
-  //     CHECK:       linalg.exp
+  //     CHECK:       linalg.elementwise
   //     CHECK:       linalg.add
   //     CHECK: return %[[RES]]
-  %0 = linalg.exp ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
   %1 = linalg.add ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
@@ -148,10 +148,10 @@ module attributes {transform.with_named_sequence} {
 func.func @fuse_unary_packed_tile_sizes_forall(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<?x?xf32> {
 
   //     CHECK: %[[RES:.*]] = scf.forall
-  //     CHECK:       linalg.exp
+  //     CHECK:       linalg.elementwise
   //     CHECK:       linalg.add
   //     CHECK: return %[[RES]]
-  %0 = linalg.exp ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
   %1 = linalg.add ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
@@ -214,10 +214,10 @@ module attributes {transform.with_named_sequence} {
 func.func @fuse_no_tiling_packed_tile_sizes(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<?x?xf32> {
 
   //     CHECK-NOT: scf.for
-  //     CHECK: linalg.exp
+  //     CHECK: linalg.elementwise
   //     CHECK: %[[RES:.*]] = linalg.add
   //     CHECK: return %[[RES]]
-  %0 = linalg.exp ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
   %1 = linalg.add ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
@@ -287,20 +287,20 @@ module attributes {transform.with_named_sequence} {
 // CHECK:         %[[RES:.*]] = scf.for
 // CHECK:           scf.for
 // CHECK:             linalg.unpack
-// CHECK:             linalg.exp
+// CHECK:             linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK:         return %[[RES]]
 func.func @unpack_elemwise(%arg0: tensor<16x48x8x8xf32>, %arg1: tensor<128x384xf32>) -> tensor<128x384xf32> {
   %0 = tensor.empty() : tensor<128x384xf32>
   %1 = linalg.unpack %arg0 inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %0
       : tensor<16x48x8x8xf32> -> tensor<128x384xf32>
-  %2 = linalg.exp ins(%1: tensor<128x384xf32>)
+  %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%1: tensor<128x384xf32>)
                              outs(%arg1: tensor<128x384xf32>) -> tensor<128x384xf32>
   return %2 : tensor<128x384xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg1 : (!transform.any_op) -> !transform.any_op
     %1, %loops:2 = transform.structured.fuse %0 tile_sizes [16, 32] interchange [0, 1]
       : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
       transform.yield
@@ -313,20 +313,20 @@ module attributes {transform.with_named_sequence} {
 // CHECK:         %[[RES:.*]] = scf.for
 // CHECK:           scf.for
 // CHECK:             linalg.pack
-// CHECK:             linalg.exp
+// CHECK:             linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK:         return %[[RES]]
 func.func @pack_elemwise(%arg0: tensor<128x384xf32>, %arg1: tensor<16x48x8x8xf32>) -> tensor<16x48x8x8xf32> {
   %0 = tensor.empty() : tensor<16x48x8x8xf32>
   %1 = linalg.pack %arg0 inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %0
       : tensor<128x384xf32> -> tensor<16x48x8x8xf32>
-  %2 = linalg.exp ins(%1: tensor<16x48x8x8xf32>)
+  %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%1: tensor<16x48x8x8xf32>)
                              outs(%arg1: tensor<16x48x8x8xf32>) -> tensor<16x48x8x8xf32>
   return %2 : tensor<16x48x8x8xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg1 : (!transform.any_op) -> !transform.any_op
     %1, %loops:2 = transform.structured.fuse %0 tile_sizes [3, 5, 0, 0]
       : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
       transform.yield
@@ -339,20 +339,20 @@ module attributes {transform.with_named_sequence} {
 // CHECK:         linalg.pack
 // CHECK:         %[[RES:.*]] = scf.for
 // CHECK:           scf.for
-// CHECK:             linalg.exp
+// CHECK:             linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK:         return %[[RES]]
 func.func @nofuse_pack_elemwise(%arg0: tensor<128x384xf32>, %arg1: tensor<16x48x8x8xf32>) -> tensor<16x48x8x8xf32> {
   %0 = tensor.empty() : tensor<16x48x8x8xf32>
   %1 = linalg.pack %arg0 inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %0
       : tensor<128x384xf32> -> tensor<16x48x8x8xf32>
-  %2 = linalg.exp ins(%1: tensor<16x48x8x8xf32>)
+  %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%1: tensor<16x48x8x8xf32>)
                              outs(%arg1: tensor<16x48x8x8xf32>) -> tensor<16x48x8x8xf32>
   return %2 : tensor<16x48x8x8xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg1 : (!transform.any_op) -> !transform.any_op
     %1, %loops:3 = transform.structured.fuse %0 tile_sizes [3, 5, 2, 0]
       : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op, !transform.any_op)
       transform.yield
@@ -366,10 +366,10 @@ func.func @fuse_through_slice(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) ->
 
   //     CHECK: %[[RES:.*]] = scf.for
   //     CHECK:     scf.for
-  //     CHECK:       linalg.exp
+  //     CHECK:       linalg.elementwise
   //     CHECK:       linalg.add
   //     CHECK: return %[[RES]]
-  %0 = linalg.exp ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg0: tensor<?x?xf32>) -> tensor<?x?xf32>
   %c0 = arith.constant 0 : index
   %c1 = arith.constant 1 : index
@@ -397,10 +397,10 @@ func.func @fuse_through_slice_and_cast_chain(%arg0: tensor<100x100xf32>, %arg1:
 
   //     CHECK: %[[RES:.*]] = scf.for
   //     CHECK:     scf.for
-  //     CHECK:       linalg.exp
+  //     CHECK:       linalg.elementwise
   //     CHECK:       linalg.add
   //     CHECK: return %[[RES]]
-  %0 = linalg.exp ins(%arg0 : tensor<100x100xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<100x100xf32>)
                              outs(%arg0: tensor<100x100xf32>) -> tensor<100x100xf32>
   %1 = tensor.cast %0 : tensor<100x100xf32> to tensor<100x?xf32>
   %2 = tensor.extract_slice %1 [1, 1] [98, 98] [1, 1] : tensor<100x?xf32> to tensor<98x98xf32>
@@ -433,7 +433,7 @@ func.func @fuse_unrelated_slices(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>)
   //     CHECK: %[[SLICE2:.+]] = tensor.extract_slice %[[SLICE1]]
   //     CHECK: %[[RES:.*]] = scf.for
   //     CHECK:     scf.for
-  //     CHECK:       linalg.exp
+  //     CHECK:       linalg.elementwise
   //     CHECK:       linalg.add
   //     CHECK: return %[[RES]], %[[SLICE2]]
   %c0 = arith.constant 0 : index
@@ -442,7 +442,7 @@ func.func @fuse_unrelated_slices(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>)
   %dim1 = tensor.dim %arg1, %c1 : tensor<?x?xf32>
   %slice1 = tensor.extract_slice %arg0 [1, 1] [%dim0, %dim1] [1, 1] : tensor<?x?xf32> to tensor<?x?xf32>
   %slice2 = tensor.extract_slice %slice1 [1, 1] [10, 10] [1, 1] : tensor<?x?xf32> to tensor<10x10xf32>
-  %0 = linalg.exp ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg0: tensor<?x?xf32>) -> tensor<?x?xf32>
   %1 = tensor.extract_slice %0 [1, 1] [%dim0, %dim1] [1, 1] : tensor<?x?xf32> to tensor<?x?xf32>
   %2 = linalg.add ins(%1, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
@@ -468,17 +468,17 @@ module attributes {transform.with_named_sequence} {
 //     CHECK:       %[[LINEAR_IDX:.+]] = affine.linearize_index disjoint [%[[X]], %[[Y]], %[[Z]]] by (2, 3, 10)
 //     CHECK:       %[[SLICE:.+]] = tensor.extract_slice %{{.*}}[%[[LINEAR_IDX]]] [5] [1] : tensor<60xf32> to tensor<5xf32>
 //     CHECK:       %[[EXPAND:.+]] = tensor.expand_shape %[[SLICE]] {{\[\[}}0, 1, 2]] output_shape [1, 1, 5]
-//     CHECK:       linalg.exp ins(%[[EXPAND]]
+//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[EXPAND]]
 func.func @bubble_up_extract_slice_through_expand_shape(%0: tensor<60xf32>) -> tensor<2x3x10xf32> {
   %expand = tensor.expand_shape %0 [[0, 1, 2]] output_shape [2, 3, 10] : tensor<60xf32> into tensor<2x3x10xf32>
   %empty = tensor.empty() : tensor<2x3x10xf32>
-  %exp = linalg.exp ins(%expand : tensor<2x3x10xf32>) outs(%empty : tensor<2x3x10xf32>) -> tensor<2x3x10xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<2x3x10xf32>) outs(%empty : tensor<2x3x10xf32>) -> tensor<2x3x10xf32>
   return %exp : tensor<2x3x10xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
     %transformed, %loops:3 = transform.structured.fuse %0 tile_sizes [1, 1, 5] interchange [0, 1, 2] apply_cleanup :
       (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">, !transform.any_op, !transform.any_op)
     transform.yield
@@ -493,17 +493,17 @@ module attributes {transform.with_named_sequence} {
 //     CHECK:       %[[LINEAR_IDX:.+]] = affine.linearize_index disjoint [%[[X]], %[[Y]]{{.*}} by (3, 4, 10)
 //     CHECK:       %[[SLICE:.+]] = tensor.extract_slice %{{.*}}[%[[LINEAR_IDX]]] [20] [1] : tensor<120xf32> to tensor<20xf32>
 //     CHECK:       %[[EXPAND:.+]] = tensor.expand_shape %[[SLICE]] {{\[\[}}0, 1, 2]] output_shape [1, 2, 10]
-//     CHECK:       linalg.exp ins(%[[EXPAND]]
+//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[EXPAND]]
 func.func @bubble_up_extract_slice_through_expand_shape_full_inner_dim(%0: tensor<120xf32>) -> tensor<3x4x10xf32> {
   %expand = tensor.expand_shape %0 [[0, 1, 2]] output_shape [3, 4, 10] : tensor<120xf32> into tensor<3x4x10xf32>
   %empty = tensor.empty() : tensor<3x4x10xf32>
-  %exp = linalg.exp ins(%expand : tensor<3x4x10xf32>) outs(%empty : tensor<3x4x10xf32>) -> tensor<3x4x10xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<3x4x10xf32>) outs(%empty : tensor<3x4x10xf32>) -> tensor<3x4x10xf32>
   return %exp : tensor<3x4x10xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
     %transformed, %loops:2 = transform.structured.fuse %0 tile_sizes [1, 2, 0] interchange [0, 1, 2] apply_cleanup :
       (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">, !transform.any_op)
     transform.yield
@@ -517,17 +517,17 @@ module attributes {transform.with_named_sequence} {
 //     CHECK: scf.for
 //     CHECK:   scf.for
 //     CHECK:     scf.for
-//     CHECK:       linalg.exp
+//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<abs>
 func.func @no_bubble_up_extract_slice_through_expand_shape_non_contiguous(%0: tensor<120xf32>) -> tensor<3x4x10xf32> {
   %expand = tensor.expand_shape %0 [[0, 1, 2]] output_shape [3, 4, 10] : tensor<120xf32> into tensor<3x4x10xf32>
   %empty = tensor.empty() : tensor<3x4x10xf32>
-  %exp = linalg.exp ins(%expand : tensor<3x4x10xf32>) outs(%empty : tensor<3x4x10xf32>) -> tensor<3x4x10xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<3x4x10xf32>) outs(%empty : tensor<3x4x10xf32>) -> tensor<3x4x10xf32>
   return %exp : tensor<3x4x10xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
     %transformed, %loops:3 = transform.structured.fuse %0 tile_sizes [1, 2, 5] interchange [0, 1, 2] apply_cleanup :
       (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">, !transform.any_op, !transform.any_op)
     transform.yield
@@ -546,19 +546,19 @@ module attributes {transform.with_named_sequence} {
 //     CHECK:       %[[LINEAR_IDX1:.+]] = affine.linearize_index disjoint [%[[Z]], %[[W]]] by (7, 8)
 //     CHECK:       %[[SLICE:.+]] = tensor.extract_slice %{{.*}}[%[[LINEAR_IDX0]], %[[LINEAR_IDX1]]] [20, 4] [1, 1] : tensor<120x56xf32> to tensor<20x4xf32>
 //     CHECK:       %[[EXPAND:.+]] = tensor.expand_shape %[[SLICE]] {{\[\[}}0, 1, 2], [3, 4]] output_shape [1, 2, 10, 1, 4]
-//     CHECK:       linalg.exp ins(%[[EXPAND]]
+//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[EXPAND]]
 module {
   func.func @bubble_up_extract_slice_through_expand_shape_multiple_expanded_dims(%0: tensor<120x56xf32>) -> tensor<3x4x10x7x8xf32> {
     %expand = tensor.expand_shape %0 [[0, 1, 2], [3, 4]] output_shape [3, 4, 10, 7, 8] : tensor<120x56xf32> into tensor<3x4x10x7x8xf32>
     %empty = tensor.empty() : tensor<3x4x10x7x8xf32>
-    %exp = linalg.exp ins(%expand : tensor<3x4x10x7x8xf32>) outs(%empty : tensor<3x4x10x7x8xf32>) -> tensor<3x4x10x7x8xf32>
+    %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<3x4x10x7x8xf32>) outs(%empty : tensor<3x4x10x7x8xf32>) -> tensor<3x4x10x7x8xf32>
     return %exp : tensor<3x4x10x7x8xf32>
   }
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
     %transformed, %loops:4 = transform.structured.fuse %0 tile_sizes [1, 2, 0, 1, 4] interchange [0, 1, 2, 3, 4] apply_cleanup :
       (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">, !transform.any_op, !transform.any_op, !transform.any_op)
     transform.yield
@@ -571,23 +571,23 @@ module attributes {transform.with_named_sequence} {
 //     CHECK: scf.for %[[X:[A-Za-z0-9]+]] = {{.*}}
 //     CHECK:    %[[LINEAR_IDX:.+]] = affine.linearize_index disjoint [%[[X]], {{.*}} by (8, 32)
 //     CHECK:    %[[SLICE:.+]] = tensor.extract_slice %{{.*}}[0, 0, %[[LINEAR_IDX]]] [1, 1800, 32] [1, 1, 1] : tensor<1x1800x256xf32> to tensor<1x1800x32xf32>
-//     CHECK:    %[[ABS:.+]] = linalg.abs ins(%[[SLICE]]
+//     CHECK:    %[[ABS:.+]] = linalg.copy ins(%[[SLICE]]
 //     CHECK:    %[[EXPAND:.+]] = tensor.expand_shape %[[ABS]] {{\[\[}}0], [1], [2, 3]] output_shape [1, 1800, 1, 32]
-//     CHECK:    linalg.exp ins(%[[EXPAND]]
+//     CHECK:    linalg.elementwise kind=#linalg.elementwise_kind<log> ins(%[[EXPAND]]
 module {
   func.func @bubble_up_extract_slice_through_expand_shape_and_fuse_with_expand_producer(%0: tensor<1x1800x256xf32>) -> tensor<1x1800x8x32xf32> {
     %empty1 = tensor.empty() : tensor<1x1800x256xf32>
-    %exp1 = linalg.abs ins(%0 : tensor<1x1800x256xf32>) outs(%empty1 : tensor<1x1800x256xf32>) -> tensor<1x1800x256xf32>
+    %exp1 = linalg.copy ins(%0 : tensor<1x1800x256xf32>) outs(%empty1 : tensor<1x1800x256xf32>) -> tensor<1x1800x256xf32>
     %expand = tensor.expand_shape %exp1 [[0], [1], [2, 3]] output_shape [1, 1800, 8, 32] : tensor<1x1800x256xf32> into tensor<1x1800x8x32xf32>
     %empty2 = tensor.empty() : tensor<1x1800x8x32xf32>
-    %exp2 = linalg.exp ins(%expand : tensor<1x1800x8x32xf32>) outs(%empty2 : tensor<1x1800x8x32xf32>) -> tensor<1x1800x8x32xf32>
+    %exp2 = linalg.elementwise kind=#linalg.elementwise_kind<log> ins(%expand : tensor<1x1800x8x32xf32>) outs(%empty2 : tensor<1x1800x8x32xf32>) -> tensor<1x1800x8x32xf32>
     return %exp2 : tensor<1x1800x8x32xf32>
   }
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
     %transformed, %loops:1 = transform.structured.fuse %0 tile_sizes [0, 0, 1, 0] interchange [0, 1, 2, 3] apply_cleanup :
       (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">)
     transform.yield
@@ -602,17 +602,17 @@ module attributes {transform.with_named_sequence} {
 //     CHECK:   scf.for %[[Y:[A-Za-z0-9]+]] = {{.*}}
 //     CHECK:     scf.for %[[Z:[A-Za-z0-9]+]] = {{.*}}
 //     CHECK:       %[[SLICE:.+]] = tensor.extract_slice %[[EXPAND]]{{.*}} [1, 1, 5] [1, 1, 1] : tensor<2x3x10xf32> to tensor<1x1x5xf32>
-//     CHECK:       linalg.exp ins(%[[SLICE]]
+//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[SLICE]]
 func.func @no_bubble_up_extract_slice_through_expand_shape_on_cleanup_false(%0: tensor<60xf32>) -> tensor<2x3x10xf32> {
   %expand = tensor.expand_shape %0 [[0, 1, 2]] output_shape [2, 3, 10] : tensor<60xf32> into tensor<2x3x10xf32>
   %empty = tensor.empty() : tensor<2x3x10xf32>
-  %exp = linalg.exp ins(%expand : tensor<2x3x10xf32>) outs(%empty : tensor<2x3x10xf32>) -> tensor<2x3x10xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<2x3x10xf32>) outs(%empty : tensor<2x3x10xf32>) -> tensor<2x3x10xf32>
   return %exp : tensor<2x3x10xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
     %transformed, %loops:3 = transform.structured.fuse %0 tile_sizes [1, 1, 5] interchange [0, 1, 2] :
       (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">, !transform.any_op, !transform.any_op)
     transform.yield
@@ -625,17 +625,17 @@ module attributes {transform.with_named_sequence} {
 // CHECK:      scf.for %[[X:[A-Za-z0-9]+]] = {{.*}} -> (tensor<8x1800x32xf32>) {
 // CHECK:             %[[EXTRACT:.*]] = tensor.extract_slice
 // CHECK:             %[[COLLAPSE:.*]] = tensor.collapse_shape %[[EXTRACT]]
-// CHECK:             %[[EXP1:.*]] = linalg.exp ins(%[[COLLAPSE]]
+// CHECK:             %[[EXP1:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[COLLAPSE]]
 func.func @bubble_up_extract_slice_through_collapse_shape(%0: tensor<1x8x1800x32xf32>) -> tensor<8x1800x32xf32> {
   %expand = tensor.collapse_shape %0 [[0, 1], [2], [3]] : tensor<1x8x1800x32xf32> into tensor<8x1800x32xf32>
   %empty = tensor.empty() : tensor<8x1800x32xf32>
-  %exp = linalg.exp ins(%expand : tensor<8x1800x32xf32>) outs(%empty : tensor<8x1800x32xf32>) -> tensor<8x1800x32xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<8x1800x32xf32>) outs(%empty : tensor<8x1800x32xf32>) -> tensor<8x1800x32xf32>
   return %exp : tensor<8x1800x32xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
     %transformed, %loops:1 = transform.structured.fuse %0 tile_sizes [1, 0, 0] interchange [0, 1, 2] apply_cleanup :
       (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">)
     transform.yield
@@ -647,21 +647,21 @@ module attributes {transform.with_named_sequence} {
 // CHECK-LABEL:   func.func @bubble_up_extract_slice_through_collapse_shape_with_collapse_producer(
 // CHECK:           scf.for %[[X:[A-Za-z0-9]+]] = {{.*}}
 // CHECK:             %[[EXTRACT:.*]] = tensor.extract_slice
-// CHECK:             %[[ABS:.*]] = linalg.abs ins(%[[EXTRACT]]
+// CHECK:             %[[ABS:.*]] = linalg.copy ins(%[[EXTRACT]]
 // CHECK:             %[[COLLAPSE:.*]] = tensor.collapse_shape %[[ABS]]
-// CHECK:             %[[EXP:.*]] = linalg.exp ins(%[[COLLAPSE]]
+// CHECK:             %[[EXP:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<log> ins(%[[COLLAPSE]]
 func.func @bubble_up_extract_slice_through_collapse_shape_with_collapse_producer(%0: tensor<1x8x1800x32xf32>) -> tensor<8x1800x32xf32> {
   %empty1 = tensor.empty() : tensor<1x8x1800x32xf32>
-  %abs = linalg.abs ins(%0 : tensor<1x8x1800x32xf32>) outs(%empty1 : tensor<1x8x1800x32xf32>) -> tensor<1x8x1800x32xf32>
+  %abs = linalg.copy ins(%0 : tensor<1x8x1800x32xf32>) outs(%empty1 : tensor<1x8x1800x32xf32>) -> tensor<1x8x1800x32xf32>
   %expand = tensor.collapse_shape %abs [[0, 1], [2], [3]] : tensor<1x8x1800x32xf32> into tensor<8x1800x32xf32>
   %empty2 = tensor.empty() : tensor<8x1800x32xf32>
-  %exp = linalg.exp ins(%expand : tensor<8x1800x32xf32>) outs(%empty2 : tensor<8x1800x32xf32>) -> tensor<8x1800x32xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<log> ins(%expand : tensor<8x1800x32xf32>) outs(%empty2 : tensor<8x1800x32xf32>) -> tensor<8x1800x32xf32>
   return %exp : tensor<8x1800x32xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
     %transformed, %loops:1 = transform.structured.fuse %0 tile_sizes [1, 0, 0] interchange [0, 1, 2] apply_cleanup :
       (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">)
     transform.yield
@@ -677,7 +677,7 @@ module attributes {transform.with_named_sequence} {
 //       CHECK:   scf.for
 //       CHECK:     tensor.extract_slice %{{.*}} [2] [1] : tensor<4xf32> to tensor<2xf32>
 //       CHECK:     linalg.generic
-//       CHECK:     linalg.exp
+//       CHECK:     linalg.elementwise kind=#linalg.elementwise_kind<abs>
 func.func @fuse_producer_semi_affine_aligned(%arg0: tensor<12xf32>, %scale: tensor<4xf32>, %init: tensor<12xf32>, %out: tensor<12xf32>) -> tensor<12xf32> {
   %0 = linalg.generic {indexing_maps = [#id, #floordiv3, #id], iterator_types = ["parallel"]}
     ins(%arg0, %scale : tensor<12xf32>, tensor<4xf32>) outs(%init : tensor<12xf32>) {
@@ -685,13 +685,13 @@ func.func @fuse_producer_semi_affine_aligned(%arg0: tensor<12xf32>, %scale: tens
     %m = arith.addf %a, %s : f32
     linalg.yield %m : f32
   } -> tensor<12xf32>
-  %1 = linalg.exp ins(%0 : tensor<12xf32>) outs(%out : tensor<12xf32>) -> tensor<12xf32>
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%0 : tensor<12xf32>) outs(%out : tensor<12xf32>) -> tensor<12xf32>
   return %1 : tensor<12xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg1 : (!transform.any_op) -> !transform.any_op
     %1, %loops = transform.structured.fuse %0 tile_sizes [6] : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
     transform.yield
   }
@@ -713,13 +713,13 @@ func.func @negative_fuse_producer_semi_affine_misaligned(%arg0: tensor<12xf32>,
     %m = arith.addf %a, %s : f32
     linalg.yield %m : f32
   } -> tensor<12xf32>
-  %1 = linalg.exp ins(%0 : tensor<12xf32>) outs(%out : tensor<12xf32>) -> tensor<12xf32>
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%0 : tensor<12xf32>) outs(%out : tensor<12xf32>) -> tensor<12xf32>
   return %1 : tensor<12xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.exp"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg1 : (!transform.any_op) -> !transform.any_op
     %1, %loops = transform.structured.fuse %0 tile_sizes [4] : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
     transform.yield
   }
diff --git a/mlir/test/Dialect/Linalg/transform-op-generalize.mlir b/mlir/test/Dialect/Linalg/transform-op-generalize.mlir
index 331c9c0fbbfd5..804d3eef4dc3c 100644
--- a/mlir/test/Dialect/Linalg/transform-op-generalize.mlir
+++ b/mlir/test/Dialect/Linalg/transform-op-generalize.mlir
@@ -3,9 +3,9 @@
 // CHECK-LABEL: func.func @generalize_unary
 func.func @generalize_unary(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<?x?xf32> {
 
-  // CHECK-NOT:   linalg.exp
+  // CHECK-NOT:   linalg.elementwise kind=#linalg.elementwise_kind<abs>
   //     CHECK:   linalg.generic
-  %0 = linalg.exp ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
   return %0 : tensor<?x?xf32>
 }
diff --git a/mlir/test/Dialect/Linalg/transform-op-specialize-elemwise-unary.mlir b/mlir/test/Dialect/Linalg/transform-op-specialize-elemwise-unary.mlir
deleted file mode 100644
index 3a2c7c9965287..0000000000000
--- a/mlir/test/Dialect/Linalg/transform-op-specialize-elemwise-unary.mlir
+++ /dev/null
@@ -1,122 +0,0 @@
-// RUN: mlir-opt --transform-interpreter --split-input-file --verify-diagnostics %s | FileCheck %s
-
-#umap = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-func.func @specialize_exp(%arg0: tensor<?x?x?xf32>, %arg1: tensor<?x?x?xf32>) -> tensor<?x?x?xf32> {
-  %0 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%arg0 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.exp %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %1 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%0 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.log %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %2 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%1 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.absf %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %3 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%2 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.ceil %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %4 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%3 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.floor %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %5 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%4 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = arith.negf %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %cst_1 = arith.constant 1.0 : f32
-  %6 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%5 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = arith.divf %cst_1, %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %7 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%6 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.round %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %8 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%7 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.sqrt %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %9 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%8 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.rsqrt %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %10 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%9 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = arith.mulf %in, %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %11 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%10 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.tanh %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  %12 = linalg.generic
-          {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]}
-          ins(%11 : tensor<?x?x?xf32>) outs(%arg1 : tensor<?x?x?xf32>) {
-  ^bb0(%in: f32, %out: f32):
-    %v = math.erf %in : f32
-    linalg.yield %v : f32
-  } -> tensor<?x?x?xf32>
-  return %12 : tensor<?x?x?xf32>
-}
-// CHECK-LABEL: specialize_exp
-// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?x?xf32>, %[[ARG1:.+]]: tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK-NOT: linalg.generic
-// CHECK: %[[RES0:.+]] = linalg.exp ins(%[[ARG0]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES1:.+]] = linalg.log ins(%[[RES0]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES2:.+]] = linalg.abs ins(%[[RES1]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES3:.+]] = linalg.ceil ins(%[[RES2]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES4:.+]] = linalg.floor ins(%[[RES3]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES5:.+]] = linalg.negf ins(%[[RES4]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES6:.+]] = linalg.reciprocal ins(%[[RES5]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES7:.+]] = linalg.round ins(%[[RES6]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES8:.+]] = linalg.sqrt ins(%[[RES7]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES9:.+]] = linalg.rsqrt ins(%[[RES8]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES10:.+]] = linalg.square ins(%[[RES9]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES11:.+]] = linalg.tanh ins(%[[RES10]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-// CHECK: %[[RES12:.+]] = linalg.erf ins(%[[RES11]] : tensor<?x?x?xf32>) outs(%[[ARG1]] : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
-
-module attributes {transform.with_named_sequence} {
-  transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match interface{LinalgOp} in %arg0 : (!transform.any_op) -> !transform.any_op
-    %1 = transform.structured.specialize %0 : (!transform.any_op) -> !transform.any_op
-    transform.yield
-  }
-}
diff --git a/mlir/test/Dialect/SCF/canonicalize.mlir b/mlir/test/Dialect/SCF/canonicalize.mlir
index 4766b1f1a7f45..37a337305159f 100644
--- a/mlir/test/Dialect/SCF/canonicalize.mlir
+++ b/mlir/test/Dialect/SCF/canonicalize.mlir
@@ -2170,7 +2170,7 @@ module {
       %4 = affine.min #map2(%arg3)[%dim, %arg0]
       %extracted_slice0 = tensor.extract_slice %arg4[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
       %extracted_slice1 = tensor.extract_slice %arg5[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
-      %5 = linalg.exp ins(%extracted_slice0 : tensor<?xf32>) outs(%extracted_slice1 : tensor<?xf32>) -> tensor<?xf32>
+      %5 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%extracted_slice0 : tensor<?xf32>) outs(%extracted_slice1 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %5 into %arg5[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
       }
@@ -2184,7 +2184,7 @@ module {
 //  CHECK-SAME:                       shared_outs(%[[ITER_ARG_5:.*]] = %[[ARG2]]) -> (tensor<?xf32>) {
 //       CHECK:      %[[OPERAND0:.*]] = tensor.extract_slice %[[ARG1]]
 //       CHECK:      %[[OPERAND1:.*]] = tensor.extract_slice %[[ITER_ARG_5]]
-//       CHECK:      %[[ELEM:.*]] = linalg.exp ins(%[[OPERAND0]] : tensor<?xf32>) outs(%[[OPERAND1]] : tensor<?xf32>) -> tensor<?xf32>
+//       CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[OPERAND0]] : tensor<?xf32>) outs(%[[OPERAND1]] : tensor<?xf32>) -> tensor<?xf32>
 //       CHECK:      scf.forall.in_parallel {
 //  CHECK-NEXT:         tensor.parallel_insert_slice %[[ELEM]] into %[[ITER_ARG_5]]
 //  CHECK-NEXT:      }
@@ -2210,7 +2210,7 @@ module {
       %extracted_slice_0 = tensor.extract_slice %arg6[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
       %extracted_slice_1 = tensor.extract_slice %arg7[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
       %extracted_slice_2 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
-      %5 = linalg.exp ins(%extracted_slice : tensor<?xf32>) outs(%extracted_slice_1 : tensor<?xf32>) -> tensor<?xf32>
+      %5 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%extracted_slice : tensor<?xf32>) outs(%extracted_slice_1 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %5 into %arg6[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
         tensor.parallel_insert_slice %extracted_slice into %arg5[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
@@ -2227,7 +2227,7 @@ module {
 //  CHECK-SAME:                       shared_outs(%[[ITER_ARG_6:.*]] = %[[ARG2]]) -> (tensor<?xf32>) {
 //       CHECK:      %[[OPERAND0:.*]] = tensor.extract_slice %[[ARG1]]
 //       CHECK:      %[[OPERAND1:.*]] = tensor.extract_slice %[[ARG3]]
-//       CHECK:      %[[ELEM:.*]] = linalg.exp ins(%[[OPERAND0]] : tensor<?xf32>) outs(%[[OPERAND1]] : tensor<?xf32>) -> tensor<?xf32>
+//       CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[OPERAND0]] : tensor<?xf32>) outs(%[[OPERAND1]] : tensor<?xf32>) -> tensor<?xf32>
 //       CHECK:      scf.forall.in_parallel {
 //  CHECK-NEXT:         tensor.parallel_insert_slice %[[ELEM]] into %[[ITER_ARG_6]]
 //  CHECK-NEXT:      }
diff --git a/mlir/test/Dialect/SCF/parallel-loop-unroll.mlir b/mlir/test/Dialect/SCF/parallel-loop-unroll.mlir
index 12b502e996c60..6e02074d18475 100644
--- a/mlir/test/Dialect/SCF/parallel-loop-unroll.mlir
+++ b/mlir/test/Dialect/SCF/parallel-loop-unroll.mlir
@@ -69,7 +69,7 @@ func.func @unroll_outer_nested_parallel_loop(%src: memref<5x16x12x4x4xf32>, %dst
       %1 = affine.apply affine_map<(d0, d1) -> (d0 + (d1 floordiv 4) * 4)>(%arg5, %arg7)
       %subv_in = memref.subview %src[%arg3, %0, %1, 0, 0] [1, 1, 1, 4, 4] [1, 1, 1, 1, 1] : memref<5x16x12x4x4xf32> to memref<4x4xf32, strided<[4, 1], offset: ?>>
       %subv_out = memref.subview %dst[%arg3, %0, %1, 0, 0] [1, 1, 1, 4, 4] [1, 1, 1, 1, 1] : memref<5x16x12x4x4xf32> to memref<4x4xf32, strided<[4, 1], offset: ?>>
-      linalg.erf ins(%subv_in : memref<4x4xf32, strided<[4, 1], offset: ?>>) outs(%subv_out : memref<4x4xf32, strided<[4, 1], offset: ?>>)
+      linalg.elementwise kind=#linalg.elementwise_kind<erf> ins(%subv_in : memref<4x4xf32, strided<[4, 1], offset: ?>>) outs(%subv_out : memref<4x4xf32, strided<[4, 1], offset: ?>>)
       scf.reduce
     }
     scf.reduce
@@ -91,13 +91,13 @@ func.func @unroll_outer_nested_parallel_loop(%src: memref<5x16x12x4x4xf32>, %dst
 // CHECK:             scf.parallel ([[INV0:%.*]], [[INV1:%.*]]) = ([[C0]], [[C0]]) to ([[C4]], [[C4]]) step ([[C1]], [[C1]])
 // CHECK:               affine.apply {{.*}}([[OUTV1]], [[INV0]])
 // CHECK:               affine.apply {{.*}}([[OUTV2]], [[INV1]])
-// CHECK:               linalg.erf
+// CHECK:               linalg.elementwise kind=#linalg.elementwise_kind<erf>
 
 // CHECK:             [[UNR_OUTV2:%.*]] = affine.apply {{.*}}([[OUTV2]])
 // CHECK:             scf.parallel ([[INV0B:%.*]], [[INV1B:%.*]]) = ([[C0]], [[C0]]) to ([[C4]], [[C4]]) step ([[C1]], [[C1]])
 // CHECK:               affine.apply {{.*}}([[OUTV1]], [[INV0B]])
 // CHECK:               affine.apply {{.*}}([[UNR_OUTV2]], [[INV1B]])
-// CHECK:               linalg.erf
+// CHECK:               linalg.elementwise kind=#linalg.elementwise_kind<erf>
 
 // -----
 
@@ -141,7 +141,7 @@ func.func @unroll_inner_nested_parallel_loop(%src: memref<5x16x12x4x4xf32>, %dst
       %1 = affine.apply affine_map<(d0, d1) -> (d0 + (d1 floordiv 4) * 4)>(%arg5, %arg7)
       %subv_in = memref.subview %src[%arg3, %0, %1, 0, 0] [1, 1, 1, 4, 4] [1, 1, 1, 1, 1] : memref<5x16x12x4x4xf32> to memref<4x4xf32, strided<[4, 1], offset: ?>>
       %subv_out = memref.subview %dst[%arg3, %0, %1, 0, 0] [1, 1, 1, 4, 4] [1, 1, 1, 1, 1] : memref<5x16x12x4x4xf32> to memref<4x4xf32, strided<[4, 1], offset: ?>>
-      linalg.erf ins(%subv_in : memref<4x4xf32, strided<[4, 1], offset: ?>>) outs(%subv_out : memref<4x4xf32, strided<[4, 1], offset: ?>>)
+      linalg.elementwise kind=#linalg.elementwise_kind<erf> ins(%subv_in : memref<4x4xf32, strided<[4, 1], offset: ?>>) outs(%subv_out : memref<4x4xf32, strided<[4, 1], offset: ?>>)
       scf.reduce
     }
     scf.reduce
@@ -163,9 +163,9 @@ func.func @unroll_inner_nested_parallel_loop(%src: memref<5x16x12x4x4xf32>, %dst
 // CHECK-UNROLL-INNER:            scf.parallel ([[INV0:%.*]], [[INV1:%.*]]) = ([[C0]], [[C0]]) to ([[C4]], [[C4]]) step ([[C1]], [[C2]])
 // CHECK-UNROLL-INNER:              affine.apply {{.*}}([[OUTV1]], [[INV0]])
 // CHECK-UNROLL-INNER:              affine.apply {{.*}}([[OUTV2]], [[INV1]])
-// CHECK-UNROLL-INNER:              linalg.erf
+// CHECK-UNROLL-INNER:              linalg.elementwise kind=#linalg.elementwise_kind<erf>
 
 // CHECK-UNROLL-INNER:              [[UNR_INV1:%.*]] = affine.apply {{.*}}([[INV1]])
 // CHECK-UNROLL-INNER:              affine.apply {{.*}}([[OUTV1]], [[INV0]])
 // CHECK-UNROLL-INNER:              affine.apply {{.*}}([[OUTV2]], [[UNR_INV1]])
-// CHECK-UNROLL-INNER:              linalg.erf
+// CHECK-UNROLL-INNER:              linalg.elementwise kind=#linalg.elementwise_kind<erf>
diff --git a/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer-using-slices.mlir b/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer-using-slices.mlir
index 62dd7faec4eb7..64de801ac6286 100644
--- a/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer-using-slices.mlir
+++ b/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer-using-slices.mlir
@@ -459,7 +459,7 @@ func.func @fuse_pack_consumer_if_single_iteration(%arg0: tensor<4x4xf32>) -> ten
     %3 = affine.min #map(%arg1)
     %extracted_slice = tensor.extract_slice %arg0[%arg1, 0] [%3, 4] [1, 1] : tensor<4x4xf32> to tensor<?x4xf32>
     %extracted_slice_0 = tensor.extract_slice %arg2[%arg1, 0] [%3, 4] [1, 1] : tensor<4x4xf32> to tensor<?x4xf32>
-    %4 = linalg.exp ins(%extracted_slice : tensor<?x4xf32>) outs(%extracted_slice_0 : tensor<?x4xf32>) -> tensor<?x4xf32>
+    %4 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%extracted_slice : tensor<?x4xf32>) outs(%extracted_slice_0 : tensor<?x4xf32>) -> tensor<?x4xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %4 into %arg2[%arg1, 0] [%3, 4] [1, 1] : tensor<?x4xf32> into tensor<4x4xf32>
     }
@@ -488,7 +488,7 @@ module attributes {transform.with_named_sequence} {
 //  CHECK-DAG:      %[[SIZE:.+]] = affine.min #[[MAP]](%[[IV]])
 //  CHECK-DAG:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][%[[IV]], 0] [%[[SIZE]], 4] [1, 1]
 //  CHECK-DAG:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[ELEM_OUT_ARG]][%[[IV]], 0] [%[[SIZE]], 4] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.exp
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[TILED_PACK_DEST:.*]] = tensor.extract_slice %[[PACK_OUT_ARG]][%[[IV]], 0, 0, 0] [1, 4, 16, 1] [1, 1, 1, 1]
@@ -506,7 +506,7 @@ func.func @fuse_perfect_tiling_pack_consumer_with_outer_dims_perm(%arg0: tensor<
   %0 = scf.forall (%arg3) = (0) to (32) step (16) shared_outs(%arg4 = %arg1) -> (tensor<64x32xf32>) {
     %src = tensor.extract_slice %arg0[0, %arg3] [64, 16] [1, 1] : tensor<64x32xf32> to tensor<64x16xf32>
     %dest = tensor.extract_slice %arg4[0, %arg3] [64, 16] [1, 1] : tensor<64x32xf32> to tensor<64x16xf32>
-    %1 = linalg.exp ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
+    %1 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %1 into %arg4[0, %arg3] [64, 16] [1, 1] : tensor<64x16xf32> into tensor<64x32xf32>
     }
@@ -532,7 +532,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:      shared_outs(%[[FIRST_OUT_ARG:.*]] = %[[ARG1]], %[[PACK_OUT_ARG:.*]] = %[[ARG2]])
 //      CHECK:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][0, %[[IV]]] [64, 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[FIRST_OUT_ARG]][0, %[[IV]]] [64, 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.exp
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[PACK_RESULT_OFFSET:.*]] = affine.apply #[[PACK_RESULT_MAP]](%[[IV]])
@@ -555,7 +555,7 @@ func.func @fuse_pack_consumer_with_no_pad_dynamic_dim(%arg0: tensor<64x?xf32>, %
   %0 = scf.forall (%arg2) = (0) to (%d1) step (16) shared_outs(%arg3 = %arg1) -> (tensor<64x?xf32>) {
     %src = tensor.extract_slice %arg0[0, %arg2] [64, 16] [1, 1] : tensor<64x?xf32> to tensor<64x16xf32>
     %dest = tensor.extract_slice %arg3[0, %arg2] [64, 16] [1, 1] : tensor<64x?xf32> to tensor<64x16xf32>
-    %2 = linalg.exp ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
+    %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %2 into %arg3[0, %arg2] [64, 16] [1, 1] : tensor<64x16xf32> into tensor<64x?xf32>
     }
@@ -581,7 +581,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:      shared_outs(%[[FIRST_OUT_ARG:.*]] = %[[ARG1]], %[[PACK_OUT_ARG:.*]] = %[[ARG2]])
 //      CHECK:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][0, %[[IV]]] [64, 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[FIRST_OUT_ARG]][0, %[[IV]]] [64, 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.exp
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[PACK_RESULT_OFFSET:.*]] = affine.apply #[[PACK_RESULT_MAP]](%[[IV]])
@@ -603,7 +603,7 @@ func.func @fuse_pack_consumer_with_padding_semantics(%arg0: tensor<64x32xf32>, %
     %size = affine.min affine_map<(d0) -> (-d0 + 64, 15)>(%arg2)
     %src = tensor.extract_slice %arg0[%arg2, %arg3] [%size, 16] [1, 1] : tensor<64x32xf32> to tensor<?x16xf32>
     %dest = tensor.extract_slice %arg4[%arg2, %arg3] [%size, 16] [1, 1] : tensor<64x32xf32> to tensor<?x16xf32>
-    %2 = linalg.exp ins(%src : tensor<?x16xf32>) outs(%dest : tensor<?x16xf32>) -> tensor<?x16xf32>
+    %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<?x16xf32>) outs(%dest : tensor<?x16xf32>) -> tensor<?x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %2 into %arg4[%arg2, %arg3] [%size, 16] [1, 1] : tensor<?x16xf32> into tensor<64x32xf32>
     }
@@ -638,7 +638,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:        [%[[I]], %[[J]]] [%[[SIZE]], 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[ELEM_OUT]]
 // CHECK-SAME:        [%[[I]], %[[J]]] [%[[SIZE]], 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.exp
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[D0_OFFSET:.*]] = affine.apply #[[MAP1]](%[[I]])
@@ -710,7 +710,7 @@ module {
         scf.yield %insert_slice : tensor<256x256xf32>
     }
     %4 = linalg.mul ins(%1, %arg2 : tensor<256x256xf32>, tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
-    %5 = linalg.exp ins(%1 : tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
+    %5 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%1 : tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
     return %4, %5 : tensor<256x256xf32>, tensor<256x256xf32>
   }
 }
@@ -742,7 +742,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:                outs(%[[ADD_OUT_SLICE]] :
 //      CHECK:          %[[INSERT_ADD:.*]] = tensor.insert_slice %[[TILED_ADD_OUT]] into %[[FIRST_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
 //      CHECK:          %[[EXP_OUT_SLICE:.*]] = tensor.extract_slice %[[SECOND_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
-//      CHECK:          %[[TILED_EXP_OUT:.*]] = linalg.exp
+//      CHECK:          %[[TILED_EXP_OUT:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME:                ins(%[[TILED_ADD_OUT]] :
 // CHECK-SAME:                outs(%[[EXP_OUT_SLICE]] :
 //      CHECK:          %[[MUL_INS2_SLICE:.*]] = tensor.extract_slice %[[ARG2]][%[[IV1]], 0] [64, 256] [1, 1]
diff --git a/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer.mlir b/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer.mlir
index 0137e2a69a46e..eae7d86873cb5 100644
--- a/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer.mlir
+++ b/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer.mlir
@@ -503,7 +503,7 @@ func.func @fuse_pack_consumer_if_single_iteration(%arg0: tensor<4x4xf32>) -> ten
     %3 = affine.min #map(%arg1)
     %extracted_slice = tensor.extract_slice %arg0[%arg1, 0] [%3, 4] [1, 1] : tensor<4x4xf32> to tensor<?x4xf32>
     %extracted_slice_0 = tensor.extract_slice %arg2[%arg1, 0] [%3, 4] [1, 1] : tensor<4x4xf32> to tensor<?x4xf32>
-    %4 = linalg.exp ins(%extracted_slice : tensor<?x4xf32>) outs(%extracted_slice_0 : tensor<?x4xf32>) -> tensor<?x4xf32>
+    %4 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%extracted_slice : tensor<?x4xf32>) outs(%extracted_slice_0 : tensor<?x4xf32>) -> tensor<?x4xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %4 into %arg2[%arg1, 0] [%3, 4] [1, 1] : tensor<?x4xf32> into tensor<4x4xf32>
     }
@@ -531,7 +531,7 @@ module attributes {transform.with_named_sequence} {
 //  CHECK-DAG:      %[[SIZE:.+]] = affine.min affine_map<(d0) -> (-d0 + 4, 16)>(%[[IV]])
 //  CHECK-DAG:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][%[[IV]], 0] [%[[SIZE]], 4] [1, 1]
 //  CHECK-DAG:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[ELEM_OUT_ARG]][%[[IV]], 0] [%[[SIZE]], 4] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.exp
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[TILED_PACK_DEST:.*]] = tensor.extract_slice %[[PACK_OUT_ARG]][%[[IV]], 0, 0, 0] [1, 4, 16, 1] [1, 1, 1, 1]
@@ -549,7 +549,7 @@ func.func @fuse_perfect_tiling_pack_consumer_with_outer_dims_perm(%arg0: tensor<
   %0 = scf.forall (%arg3) = (0) to (32) step (16) shared_outs(%arg4 = %arg1) -> (tensor<64x32xf32>) {
     %src = tensor.extract_slice %arg0[0, %arg3] [64, 16] [1, 1] : tensor<64x32xf32> to tensor<64x16xf32>
     %dest = tensor.extract_slice %arg4[0, %arg3] [64, 16] [1, 1] : tensor<64x32xf32> to tensor<64x16xf32>
-    %1 = linalg.exp ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
+    %1 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %1 into %arg4[0, %arg3] [64, 16] [1, 1] : tensor<64x16xf32> into tensor<64x32xf32>
     }
@@ -574,7 +574,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:      shared_outs(%[[FIRST_OUT_ARG:.*]] = %[[ARG1]], %[[PACK_OUT_ARG:.*]] = %[[ARG2]])
 //      CHECK:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][0, %[[IV]]] [64, 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[FIRST_OUT_ARG]][0, %[[IV]]] [64, 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.exp
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[PACK_RESULT_OFFSET:.*]] = affine.apply affine_map<(d0) -> (d0 floordiv 16)>(%[[IV]])
@@ -597,7 +597,7 @@ func.func @fuse_pack_consumer_with_no_pad_dynamic_dim(%arg0: tensor<64x?xf32>, %
   %0 = scf.forall (%arg2) = (0) to (%d1) step (16) shared_outs(%arg3 = %arg1) -> (tensor<64x?xf32>) {
     %src = tensor.extract_slice %arg0[0, %arg2] [64, 16] [1, 1] : tensor<64x?xf32> to tensor<64x16xf32>
     %dest = tensor.extract_slice %arg3[0, %arg2] [64, 16] [1, 1] : tensor<64x?xf32> to tensor<64x16xf32>
-    %2 = linalg.exp ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
+    %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %2 into %arg3[0, %arg2] [64, 16] [1, 1] : tensor<64x16xf32> into tensor<64x?xf32>
     }
@@ -622,7 +622,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:      shared_outs(%[[FIRST_OUT_ARG:.*]] = %[[ARG1]], %[[PACK_OUT_ARG:.*]] = %[[ARG2]])
 //      CHECK:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][0, %[[IV]]] [64, 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[FIRST_OUT_ARG]][0, %[[IV]]] [64, 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.exp
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[PACK_RESULT_OFFSET:.*]] = affine.apply affine_map<(d0) -> (d0 floordiv 16)>(%[[IV]])
@@ -644,7 +644,7 @@ func.func @fuse_pack_consumer_with_padding_semantics(%arg0: tensor<64x32xf32>, %
     %size = affine.min affine_map<(d0) -> (-d0 + 64, 15)>(%arg2)
     %src = tensor.extract_slice %arg0[%arg2, %arg3] [%size, 16] [1, 1] : tensor<64x32xf32> to tensor<?x16xf32>
     %dest = tensor.extract_slice %arg4[%arg2, %arg3] [%size, 16] [1, 1] : tensor<64x32xf32> to tensor<?x16xf32>
-    %2 = linalg.exp ins(%src : tensor<?x16xf32>) outs(%dest : tensor<?x16xf32>) -> tensor<?x16xf32>
+    %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<?x16xf32>) outs(%dest : tensor<?x16xf32>) -> tensor<?x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %2 into %arg4[%arg2, %arg3] [%size, 16] [1, 1] : tensor<?x16xf32> into tensor<64x32xf32>
     }
@@ -675,7 +675,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:        [%[[I]], %[[J]]] [%[[SIZE]], 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[ELEM_OUT]]
 // CHECK-SAME:        [%[[I]], %[[J]]] [%[[SIZE]], 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.exp
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[D0_OFFSET:.*]] = affine.apply affine_map<(d0) -> (d0 floordiv 3)>(%[[I]])
@@ -748,7 +748,7 @@ module {
         scf.yield %insert_slice : tensor<256x256xf32>
     }
     %4 = linalg.mul ins(%1, %arg2 : tensor<256x256xf32>, tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
-    %5 = linalg.exp ins(%1 : tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
+    %5 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%1 : tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
     return %4, %5 : tensor<256x256xf32>, tensor<256x256xf32>
   }
 }
@@ -761,7 +761,7 @@ module attributes {transform.with_named_sequence} {
       : (!transform.any_op) -> !transform.any_op
     %fused_consumer, %new_loop = transform.test.fuse_consumer %mulop into (%loop)
       : (!transform.any_op, !transform.any_op) -> (!transform.any_op, !transform.any_op)
-    %expop = transform.structured.match ops{["linalg.exp"]} in %arg1
+    %expop = transform.structured.match ops{["linalg.elementwise"]} in %arg1
       : (!transform.any_op) -> !transform.any_op
     %fused_consumer_2, %new_loop_2 = transform.test.fuse_consumer %expop into (%new_loop)
       : (!transform.any_op, !transform.any_op) -> (!transform.any_op, !transform.any_op)
@@ -789,7 +789,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:                ins(%[[TILED_ADD_OUT]], %[[MUL_INS2_SLICE]] :
 // CHECK-SAME:                outs(%[[MUL_OUT_SLICE]] :
 //      CHECK:          %[[EXP_OUT_SLICE:.*]] = tensor.extract_slice %[[THIRD_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
-//      CHECK:          %[[TILED_EXP_OUT:.*]] = linalg.exp
+//      CHECK:          %[[TILED_EXP_OUT:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
 // CHECK-SAME:                ins(%[[TILED_ADD_OUT]] :
 // CHECK-SAME:                outs(%[[EXP_OUT_SLICE]] :
 //      CHECK:          %[[INSERT_MUL:.*]] = tensor.insert_slice %[[TILED_MUL_OUT]] into %[[SECOND_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
diff --git a/mlir/test/python/dialects/linalg/opdsl/test_core_named_ops.py b/mlir/test/python/dialects/linalg/opdsl/test_core_named_ops.py
index bc273bfa06f86..fad6c903ed1f8 100644
--- a/mlir/test/python/dialects/linalg/opdsl/test_core_named_ops.py
+++ b/mlir/test/python/dialects/linalg/opdsl/test_core_named_ops.py
@@ -3,6 +3,5 @@
 # Just verify that at least one known op is generated.
 # CHECK: name: copy
 
-# verify some special cases: negf->NegFOp, powf->PowFOp
-# CHECK cpp_class_name: NegFOp
+# verify some special cases: powf->PowFOp
 # CHECK cpp_class_name: PowFOp

>From e82b751bf8ae8373664b2df1d016b6bbd43ff59e Mon Sep 17 00:00:00 2001
From: rengolin <rengolin at systemcall.eu>
Date: Fri, 4 Sep 2026 08:51:51 -0700
Subject: [PATCH 2/2] Revert spurious operation type changes

---
 .../linalg-morph-elementwise-to-named.mlir    |  5 +-
 .../Dialect/Linalg/match-ops-interpreter.mlir |  4 +-
 ...oundtrip-morphism-linalg-category-ops.mlir |  6 ++
 .../Linalg/specialize-generic-ops.mlir        |  5 +-
 .../transform-op-fuse-into-containing.mlir    | 36 +++++------
 .../Dialect/Linalg/transform-op-fuse.mlir     | 62 +++++++++----------
 .../Linalg/transform-op-generalize.mlir       |  4 +-
 mlir/test/Dialect/SCF/canonicalize.mlir       |  8 +--
 .../tile-and-fuse-consumer-using-slices.mlir  | 20 +++---
 .../tile-and-fuse-consumer.mlir               | 20 +++---
 10 files changed, 87 insertions(+), 83 deletions(-)

diff --git a/mlir/test/Dialect/Linalg/linalg-morph-elementwise-to-named.mlir b/mlir/test/Dialect/Linalg/linalg-morph-elementwise-to-named.mlir
index fdf30be6e9e9d..63550cf92e2c4 100644
--- a/mlir/test/Dialect/Linalg/linalg-morph-elementwise-to-named.mlir
+++ b/mlir/test/Dialect/Linalg/linalg-morph-elementwise-to-named.mlir
@@ -135,7 +135,7 @@ func.func @ternary_select(%A: tensor<?x?xi1>, %B: tensor<?x?xf32>,
 // Non-identity indexing maps: should NOT be converted to named op.
 func.func @non_identity_maps(%A: tensor<?xf32>, %Out: tensor<?x?xf32>) -> tensor<?x?xf32> {
   %0 = linalg.elementwise
-    kind=#linalg.elementwise_kind<abs>
+    kind=#linalg.elementwise_kind<exp>
     indexing_maps = [affine_map<(d0, d1) -> (d1)>, affine_map<(d0, d1) -> (d0, d1)>]
     ins(%A : tensor<?xf32>) outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
   return %0 : tensor<?x?xf32>
@@ -143,10 +143,9 @@ func.func @non_identity_maps(%A: tensor<?xf32>, %Out: tensor<?x?xf32>) -> tensor
 
 // CHECK-LABEL: non_identity_maps
 // CHECK-SAME: %[[A:.+]]: tensor<?xf32>, %[[OUT:.+]]: tensor<?x?xf32>)
-// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<abs>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME: ins(%[[A]] : tensor<?xf32>)
 // CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK-NOT: linalg.abs
 
 // -----
 
diff --git a/mlir/test/Dialect/Linalg/match-ops-interpreter.mlir b/mlir/test/Dialect/Linalg/match-ops-interpreter.mlir
index e8333fb5122be..2718378252403 100644
--- a/mlir/test/Dialect/Linalg/match-ops-interpreter.mlir
+++ b/mlir/test/Dialect/Linalg/match-ops-interpreter.mlir
@@ -846,11 +846,11 @@ module attributes { transform.with_named_sequence } {
     // expected-remark @below {{matched result value}}
     // expected-remark @below {{op result}}
     // expected-note @below {{value handle points to an op result #0}}
-    linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%3 : tensor<42x42xf32>) outs(%0 : tensor<42x42xf32>) -> tensor<42x42xf32>
+    linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%3 : tensor<42x42xf32>) outs(%0 : tensor<42x42xf32>) -> tensor<42x42xf32>
     // expected-remark @below {{matched result value}}
     // expected-remark @below {{op result}}
     // expected-note @below {{value handle points to an op result #0}}
-    linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%3 : tensor<42x42xf32>) outs(%0 : tensor<42x42xf32>) -> tensor<42x42xf32>
+    linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%3 : tensor<42x42xf32>) outs(%0 : tensor<42x42xf32>) -> tensor<42x42xf32>
     return
   }
 }
diff --git a/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-category-ops.mlir b/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-category-ops.mlir
index fb234825d187c..b9d7db6227816 100644
--- a/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-category-ops.mlir
+++ b/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-category-ops.mlir
@@ -6,6 +6,8 @@
 // RUN: | FileCheck %s
 
 func.func @unary_ops(%A: memref<7x14x21xf32>, %Out: memref<7x14x21xf32>) {
+  linalg.elementwise kind=#linalg.elementwise_kind<exp>
+    ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
   linalg.elementwise kind=#linalg.elementwise_kind<log>
     ins(%A : memref<7x14x21xf32>) outs(%Out : memref<7x14x21xf32>)
   linalg.elementwise kind=#linalg.elementwise_kind<abs>
@@ -59,6 +61,10 @@ func.func @unary_ops(%A: memref<7x14x21xf32>, %Out: memref<7x14x21xf32>) {
 
 // CHECK-LABEL: unary_ops
 // CHECK-SAME: %[[A:.+]]: memref<7x14x21xf32>, %[[OUT:.+]]: memref<7x14x21xf32>)
+// CHECK-NOT: linalg.generic
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+// CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
+// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
 // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<log>
 // CHECK-SAME: ins(%[[A]] : memref<7x14x21xf32>)
 // CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
diff --git a/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir b/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir
index 2961de3a8d945..01e06908c32d5 100644
--- a/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir
+++ b/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir
@@ -237,7 +237,7 @@ func.func @unary_ops_non_identity(%A: tensor<?xf32>, %Out: tensor<?x?xf32>) -> t
     ins(%A : tensor<?xf32>)
     outs(%Out : tensor<?x?xf32>) {
   ^bb0(%in: f32, %out: f32):  
-    %v = math.absf %in : f32
+    %v = math.exp %in : f32
     linalg.yield %v : f32
   } -> tensor<?x?xf32>
   return %0 : tensor<?x?xf32>
@@ -250,11 +250,10 @@ func.func @unary_ops_non_identity(%A: tensor<?xf32>, %Out: tensor<?x?xf32>) -> t
 // ALL-SAME: %[[A:.+]]: tensor<?xf32>, %[[OUT:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
 
 // Named ops cannot carry user-defined indexing maps -> expect no change.
-// NAMED-NOT: linalg.abs
 // NAMED: linalg.generic
 
 // CATEGORY-NOT: linalg.generic
-// CATEGORY: linalg.elementwise kind=#linalg.elementwise_kind<abs>
+// CATEGORY: linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CATEGORY-SAME: indexing_maps = [#[[MAP_BC]], #[[MAP_TP]]]
 // CATEGORY-SAME: ins(%[[A]] : tensor<?xf32>)
 // CATEGORY-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
diff --git a/mlir/test/Dialect/Linalg/transform-op-fuse-into-containing.mlir b/mlir/test/Dialect/Linalg/transform-op-fuse-into-containing.mlir
index f7019e79ca73c..29a3a8ac7f95d 100644
--- a/mlir/test/Dialect/Linalg/transform-op-fuse-into-containing.mlir
+++ b/mlir/test/Dialect/Linalg/transform-op-fuse-into-containing.mlir
@@ -26,8 +26,8 @@ module {
       // CHECK: %[[T1:.*]] = linalg.fill {{.*}} outs(%[[T0]]
       %6 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[T1]]
-      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[T1]]
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
       }
@@ -76,8 +76,8 @@ module {
       %4 = affine.min #map2(%arg3)[%arg0]
       %5 = tensor.extract_slice %o[%3] [%4] [1] : tensor<64xf32> to tensor<?xf32>
 
-      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[INIT_TENSOR]]
-      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%0 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[INIT_TENSOR]]
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%0 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<64xf32>
       }
@@ -177,8 +177,8 @@ module {
       // CHECK: %[[T1:.*]] = linalg.fill {{.*}} outs(%[[T0]]
       %6 = tensor.extract_slice %arg1[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> {{.*}} outs(%[[T1]]
-      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp> {{.*}} outs(%[[T1]]
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
       }
@@ -228,8 +228,8 @@ module {
       // CHECK: %[[T2:.*]] = linalg.fill {{.*}} outs(%[[T1]]
       %6 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      // CHECK: %[[T3:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[T2]] : tensor<?xf32>) outs(%[[T0]] : tensor<?xf32>)
-      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      // CHECK: %[[T3:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[T2]] : tensor<?xf32>) outs(%[[T0]] : tensor<?xf32>)
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
       }
@@ -308,10 +308,10 @@ module {
           // CHECK:  %[[EX1:.*]] = tensor.extract_slice %[[BBARG2]]{{.*}}: tensor<?x?x?xf32> to tensor<1x1x1xf32>
           // CHECK:  linalg.elementwise kind=#linalg.elementwise_kind<abs> ins({{.*}} : tensor<1x1x1xf32>) outs(%[[EX1]] : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
           // CHECK:  %[[EX2:.*]] = tensor.extract_slice %[[BBARG2]]{{.*}} : tensor<?x?x?xf32> to tensor<1x1x1xf32>
-          // CHECK:  linalg.elementwise kind=#linalg.elementwise_kind<abs> ins({{.*}} : tensor<1x1x1xf32>) outs(%[[EX2]] : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
+          // CHECK:  linalg.elementwise kind=#linalg.elementwise_kind<exp> ins({{.*}} : tensor<1x1x1xf32>) outs(%[[EX2]] : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
           %extracted_slice = tensor.extract_slice %0[%arg2, %arg4, %arg6] [1, 1, 1] [1, 1, 1] : tensor<?x?x?xf32> to tensor<1x1x1xf32>
           %extracted_slice_2 = tensor.extract_slice %arg7[%arg2, %arg4, %arg6] [1, 1, 1] [1, 1, 1] : tensor<?x?x?xf32> to tensor<1x1x1xf32>
-          %4 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%extracted_slice : tensor<1x1x1xf32>) outs(%extracted_slice_2 : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
+          %4 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%extracted_slice : tensor<1x1x1xf32>) outs(%extracted_slice_2 : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
           %inserted_slice = tensor.insert_slice %4 into %arg7[%arg2, %arg4, %arg6] [1, 1, 1] [1, 1, 1] : tensor<1x1x1xf32> into tensor<?x?x?xf32>
           scf.yield %inserted_slice : tensor<?x?x?xf32>
         }
@@ -374,8 +374,8 @@ module {
       // CHECK: %[[T1:.*]]:2 = linalg.generic {{.*}} ins(%[[T0]]
       %6 = tensor.extract_slice %0#0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[T1]]#0
-      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      // CHECK: %[[T2:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[T1]]#0
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
       }
@@ -410,8 +410,8 @@ module {
       %2 = tensor.extract_slice %0[%i][1][1] : tensor<2xf32> to tensor<1xf32>
       %3 = tensor.extract_slice %arg1[%i][1][1] : tensor<2xf32> to tensor<1xf32>
       // CHECK: %[[FUSED:.+]] = linalg.fill
-      // CHECK: elementwise kind=#linalg.elementwise_kind<abs> ins(%[[FUSED]]
-      %4 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%2 : tensor<1xf32>) outs(%3 : tensor<1xf32>) -> tensor<1xf32>
+      // CHECK: elementwise kind=#linalg.elementwise_kind<exp> ins(%[[FUSED]]
+      %4 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%2 : tensor<1xf32>) outs(%3 : tensor<1xf32>) -> tensor<1xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %4 into %arg1[%i][1][1] : tensor<1xf32> into tensor<2xf32>
       }
@@ -480,7 +480,7 @@ module {
       // CHECK: %[[T1:.*]]:2 = linalg.generic {{.*}}
       %6 = tensor.extract_slice %0#0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         // CHECK: tensor.parallel_insert_slice %[[T1]]#0 into %[[ARG7]][%[[I0]]] [%[[I1]]] [1] : tensor<?xf32> into tensor<?xf32>
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
@@ -549,7 +549,7 @@ module {
       // CHECK: %[[T1:.*]] = linalg.generic {{.*}}
       %6 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         // CHECK: tensor.parallel_insert_slice %[[T1]] into %[[ARG7]][%[[I0]]] [%[[I1]]] [1] : tensor<?xf32> into tensor<?xf32>
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
@@ -616,7 +616,7 @@ module {
       // CHECK: %[[T1:.*]] = linalg.generic {{.*}}
       %6 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
 
-      %7 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
+      %7 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%6 : tensor<?xf32>) outs(%5 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         // CHECK: tensor.parallel_insert_slice %[[T1]] into %[[ARG7]][%[[I0]]] [%[[I1]]] [1] : tensor<?xf32> into tensor<?xf32>
         tensor.parallel_insert_slice %7 into %o[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
@@ -692,7 +692,7 @@ module {
       // CHECK: %[[T2:.*]] = linalg.generic {{.*}}
       %7 = tensor.extract_slice %1[%4] [%5] [1] : tensor<?xf32> to tensor<?xf32>
 
-      %8 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%7 : tensor<?xf32>) outs(%6 : tensor<?xf32>) -> tensor<?xf32>
+      %8 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%7 : tensor<?xf32>) outs(%6 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         // CHECK: tensor.parallel_insert_slice %[[T2]] into %[[ARG7]][%[[I0]]] [%[[I1]]] [1] : tensor<?xf32> into tensor<?xf32>
         tensor.parallel_insert_slice %8 into %o[%2] [%5] [1] : tensor<?xf32> into tensor<?xf32>
diff --git a/mlir/test/Dialect/Linalg/transform-op-fuse.mlir b/mlir/test/Dialect/Linalg/transform-op-fuse.mlir
index 5dffd4070b49c..e937bc2cb0b89 100644
--- a/mlir/test/Dialect/Linalg/transform-op-fuse.mlir
+++ b/mlir/test/Dialect/Linalg/transform-op-fuse.mlir
@@ -287,13 +287,13 @@ module attributes {transform.with_named_sequence} {
 // CHECK:         %[[RES:.*]] = scf.for
 // CHECK:           scf.for
 // CHECK:             linalg.unpack
-// CHECK:             linalg.elementwise kind=#linalg.elementwise_kind<abs>
+// CHECK:             linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK:         return %[[RES]]
 func.func @unpack_elemwise(%arg0: tensor<16x48x8x8xf32>, %arg1: tensor<128x384xf32>) -> tensor<128x384xf32> {
   %0 = tensor.empty() : tensor<128x384xf32>
   %1 = linalg.unpack %arg0 inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %0
       : tensor<16x48x8x8xf32> -> tensor<128x384xf32>
-  %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%1: tensor<128x384xf32>)
+  %2 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%1: tensor<128x384xf32>)
                              outs(%arg1: tensor<128x384xf32>) -> tensor<128x384xf32>
   return %2 : tensor<128x384xf32>
 }
@@ -313,13 +313,13 @@ module attributes {transform.with_named_sequence} {
 // CHECK:         %[[RES:.*]] = scf.for
 // CHECK:           scf.for
 // CHECK:             linalg.pack
-// CHECK:             linalg.elementwise kind=#linalg.elementwise_kind<abs>
+// CHECK:             linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK:         return %[[RES]]
 func.func @pack_elemwise(%arg0: tensor<128x384xf32>, %arg1: tensor<16x48x8x8xf32>) -> tensor<16x48x8x8xf32> {
   %0 = tensor.empty() : tensor<16x48x8x8xf32>
   %1 = linalg.pack %arg0 inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %0
       : tensor<128x384xf32> -> tensor<16x48x8x8xf32>
-  %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%1: tensor<16x48x8x8xf32>)
+  %2 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%1: tensor<16x48x8x8xf32>)
                              outs(%arg1: tensor<16x48x8x8xf32>) -> tensor<16x48x8x8xf32>
   return %2 : tensor<16x48x8x8xf32>
 }
@@ -339,13 +339,13 @@ module attributes {transform.with_named_sequence} {
 // CHECK:         linalg.pack
 // CHECK:         %[[RES:.*]] = scf.for
 // CHECK:           scf.for
-// CHECK:             linalg.elementwise kind=#linalg.elementwise_kind<abs>
+// CHECK:             linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK:         return %[[RES]]
 func.func @nofuse_pack_elemwise(%arg0: tensor<128x384xf32>, %arg1: tensor<16x48x8x8xf32>) -> tensor<16x48x8x8xf32> {
   %0 = tensor.empty() : tensor<16x48x8x8xf32>
   %1 = linalg.pack %arg0 inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %0
       : tensor<128x384xf32> -> tensor<16x48x8x8xf32>
-  %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%1: tensor<16x48x8x8xf32>)
+  %2 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%1: tensor<16x48x8x8xf32>)
                              outs(%arg1: tensor<16x48x8x8xf32>) -> tensor<16x48x8x8xf32>
   return %2 : tensor<16x48x8x8xf32>
 }
@@ -468,11 +468,11 @@ module attributes {transform.with_named_sequence} {
 //     CHECK:       %[[LINEAR_IDX:.+]] = affine.linearize_index disjoint [%[[X]], %[[Y]], %[[Z]]] by (2, 3, 10)
 //     CHECK:       %[[SLICE:.+]] = tensor.extract_slice %{{.*}}[%[[LINEAR_IDX]]] [5] [1] : tensor<60xf32> to tensor<5xf32>
 //     CHECK:       %[[EXPAND:.+]] = tensor.expand_shape %[[SLICE]] {{\[\[}}0, 1, 2]] output_shape [1, 1, 5]
-//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[EXPAND]]
+//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[EXPAND]]
 func.func @bubble_up_extract_slice_through_expand_shape(%0: tensor<60xf32>) -> tensor<2x3x10xf32> {
   %expand = tensor.expand_shape %0 [[0, 1, 2]] output_shape [2, 3, 10] : tensor<60xf32> into tensor<2x3x10xf32>
   %empty = tensor.empty() : tensor<2x3x10xf32>
-  %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<2x3x10xf32>) outs(%empty : tensor<2x3x10xf32>) -> tensor<2x3x10xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%expand : tensor<2x3x10xf32>) outs(%empty : tensor<2x3x10xf32>) -> tensor<2x3x10xf32>
   return %exp : tensor<2x3x10xf32>
 }
 
@@ -493,11 +493,11 @@ module attributes {transform.with_named_sequence} {
 //     CHECK:       %[[LINEAR_IDX:.+]] = affine.linearize_index disjoint [%[[X]], %[[Y]]{{.*}} by (3, 4, 10)
 //     CHECK:       %[[SLICE:.+]] = tensor.extract_slice %{{.*}}[%[[LINEAR_IDX]]] [20] [1] : tensor<120xf32> to tensor<20xf32>
 //     CHECK:       %[[EXPAND:.+]] = tensor.expand_shape %[[SLICE]] {{\[\[}}0, 1, 2]] output_shape [1, 2, 10]
-//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[EXPAND]]
+//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[EXPAND]]
 func.func @bubble_up_extract_slice_through_expand_shape_full_inner_dim(%0: tensor<120xf32>) -> tensor<3x4x10xf32> {
   %expand = tensor.expand_shape %0 [[0, 1, 2]] output_shape [3, 4, 10] : tensor<120xf32> into tensor<3x4x10xf32>
   %empty = tensor.empty() : tensor<3x4x10xf32>
-  %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<3x4x10xf32>) outs(%empty : tensor<3x4x10xf32>) -> tensor<3x4x10xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%expand : tensor<3x4x10xf32>) outs(%empty : tensor<3x4x10xf32>) -> tensor<3x4x10xf32>
   return %exp : tensor<3x4x10xf32>
 }
 
@@ -517,11 +517,11 @@ module attributes {transform.with_named_sequence} {
 //     CHECK: scf.for
 //     CHECK:   scf.for
 //     CHECK:     scf.for
-//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<exp>
 func.func @no_bubble_up_extract_slice_through_expand_shape_non_contiguous(%0: tensor<120xf32>) -> tensor<3x4x10xf32> {
   %expand = tensor.expand_shape %0 [[0, 1, 2]] output_shape [3, 4, 10] : tensor<120xf32> into tensor<3x4x10xf32>
   %empty = tensor.empty() : tensor<3x4x10xf32>
-  %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<3x4x10xf32>) outs(%empty : tensor<3x4x10xf32>) -> tensor<3x4x10xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%expand : tensor<3x4x10xf32>) outs(%empty : tensor<3x4x10xf32>) -> tensor<3x4x10xf32>
   return %exp : tensor<3x4x10xf32>
 }
 
@@ -546,12 +546,12 @@ module attributes {transform.with_named_sequence} {
 //     CHECK:       %[[LINEAR_IDX1:.+]] = affine.linearize_index disjoint [%[[Z]], %[[W]]] by (7, 8)
 //     CHECK:       %[[SLICE:.+]] = tensor.extract_slice %{{.*}}[%[[LINEAR_IDX0]], %[[LINEAR_IDX1]]] [20, 4] [1, 1] : tensor<120x56xf32> to tensor<20x4xf32>
 //     CHECK:       %[[EXPAND:.+]] = tensor.expand_shape %[[SLICE]] {{\[\[}}0, 1, 2], [3, 4]] output_shape [1, 2, 10, 1, 4]
-//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[EXPAND]]
+//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[EXPAND]]
 module {
   func.func @bubble_up_extract_slice_through_expand_shape_multiple_expanded_dims(%0: tensor<120x56xf32>) -> tensor<3x4x10x7x8xf32> {
     %expand = tensor.expand_shape %0 [[0, 1, 2], [3, 4]] output_shape [3, 4, 10, 7, 8] : tensor<120x56xf32> into tensor<3x4x10x7x8xf32>
     %empty = tensor.empty() : tensor<3x4x10x7x8xf32>
-    %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<3x4x10x7x8xf32>) outs(%empty : tensor<3x4x10x7x8xf32>) -> tensor<3x4x10x7x8xf32>
+    %exp = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%expand : tensor<3x4x10x7x8xf32>) outs(%empty : tensor<3x4x10x7x8xf32>) -> tensor<3x4x10x7x8xf32>
     return %exp : tensor<3x4x10x7x8xf32>
   }
 }
@@ -571,23 +571,23 @@ module attributes {transform.with_named_sequence} {
 //     CHECK: scf.for %[[X:[A-Za-z0-9]+]] = {{.*}}
 //     CHECK:    %[[LINEAR_IDX:.+]] = affine.linearize_index disjoint [%[[X]], {{.*}} by (8, 32)
 //     CHECK:    %[[SLICE:.+]] = tensor.extract_slice %{{.*}}[0, 0, %[[LINEAR_IDX]]] [1, 1800, 32] [1, 1, 1] : tensor<1x1800x256xf32> to tensor<1x1800x32xf32>
-//     CHECK:    %[[ABS:.+]] = linalg.copy ins(%[[SLICE]]
+//     CHECK:    %[[ABS:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[SLICE]]
 //     CHECK:    %[[EXPAND:.+]] = tensor.expand_shape %[[ABS]] {{\[\[}}0], [1], [2, 3]] output_shape [1, 1800, 1, 32]
-//     CHECK:    linalg.elementwise kind=#linalg.elementwise_kind<log> ins(%[[EXPAND]]
+//     CHECK:    linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[EXPAND]]
 module {
   func.func @bubble_up_extract_slice_through_expand_shape_and_fuse_with_expand_producer(%0: tensor<1x1800x256xf32>) -> tensor<1x1800x8x32xf32> {
     %empty1 = tensor.empty() : tensor<1x1800x256xf32>
-    %exp1 = linalg.copy ins(%0 : tensor<1x1800x256xf32>) outs(%empty1 : tensor<1x1800x256xf32>) -> tensor<1x1800x256xf32>
+    %exp1 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%0 : tensor<1x1800x256xf32>) outs(%empty1 : tensor<1x1800x256xf32>) -> tensor<1x1800x256xf32>
     %expand = tensor.expand_shape %exp1 [[0], [1], [2, 3]] output_shape [1, 1800, 8, 32] : tensor<1x1800x256xf32> into tensor<1x1800x8x32xf32>
     %empty2 = tensor.empty() : tensor<1x1800x8x32xf32>
-    %exp2 = linalg.elementwise kind=#linalg.elementwise_kind<log> ins(%expand : tensor<1x1800x8x32xf32>) outs(%empty2 : tensor<1x1800x8x32xf32>) -> tensor<1x1800x8x32xf32>
+    %exp2 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%expand : tensor<1x1800x8x32xf32>) outs(%empty2 : tensor<1x1800x8x32xf32>) -> tensor<1x1800x8x32xf32>
     return %exp2 : tensor<1x1800x8x32xf32>
   }
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<exp>} in %arg0 : (!transform.any_op) -> !transform.any_op
     %transformed, %loops:1 = transform.structured.fuse %0 tile_sizes [0, 0, 1, 0] interchange [0, 1, 2, 3] apply_cleanup :
       (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">)
     transform.yield
@@ -602,11 +602,11 @@ module attributes {transform.with_named_sequence} {
 //     CHECK:   scf.for %[[Y:[A-Za-z0-9]+]] = {{.*}}
 //     CHECK:     scf.for %[[Z:[A-Za-z0-9]+]] = {{.*}}
 //     CHECK:       %[[SLICE:.+]] = tensor.extract_slice %[[EXPAND]]{{.*}} [1, 1, 5] [1, 1, 1] : tensor<2x3x10xf32> to tensor<1x1x5xf32>
-//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[SLICE]]
+//     CHECK:       linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[SLICE]]
 func.func @no_bubble_up_extract_slice_through_expand_shape_on_cleanup_false(%0: tensor<60xf32>) -> tensor<2x3x10xf32> {
   %expand = tensor.expand_shape %0 [[0, 1, 2]] output_shape [2, 3, 10] : tensor<60xf32> into tensor<2x3x10xf32>
   %empty = tensor.empty() : tensor<2x3x10xf32>
-  %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<2x3x10xf32>) outs(%empty : tensor<2x3x10xf32>) -> tensor<2x3x10xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%expand : tensor<2x3x10xf32>) outs(%empty : tensor<2x3x10xf32>) -> tensor<2x3x10xf32>
   return %exp : tensor<2x3x10xf32>
 }
 
@@ -625,11 +625,11 @@ module attributes {transform.with_named_sequence} {
 // CHECK:      scf.for %[[X:[A-Za-z0-9]+]] = {{.*}} -> (tensor<8x1800x32xf32>) {
 // CHECK:             %[[EXTRACT:.*]] = tensor.extract_slice
 // CHECK:             %[[COLLAPSE:.*]] = tensor.collapse_shape %[[EXTRACT]]
-// CHECK:             %[[EXP1:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[COLLAPSE]]
+// CHECK:             %[[EXP1:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[COLLAPSE]]
 func.func @bubble_up_extract_slice_through_collapse_shape(%0: tensor<1x8x1800x32xf32>) -> tensor<8x1800x32xf32> {
   %expand = tensor.collapse_shape %0 [[0, 1], [2], [3]] : tensor<1x8x1800x32xf32> into tensor<8x1800x32xf32>
   %empty = tensor.empty() : tensor<8x1800x32xf32>
-  %exp = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%expand : tensor<8x1800x32xf32>) outs(%empty : tensor<8x1800x32xf32>) -> tensor<8x1800x32xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%expand : tensor<8x1800x32xf32>) outs(%empty : tensor<8x1800x32xf32>) -> tensor<8x1800x32xf32>
   return %exp : tensor<8x1800x32xf32>
 }
 
@@ -647,21 +647,21 @@ module attributes {transform.with_named_sequence} {
 // CHECK-LABEL:   func.func @bubble_up_extract_slice_through_collapse_shape_with_collapse_producer(
 // CHECK:           scf.for %[[X:[A-Za-z0-9]+]] = {{.*}}
 // CHECK:             %[[EXTRACT:.*]] = tensor.extract_slice
-// CHECK:             %[[ABS:.*]] = linalg.copy ins(%[[EXTRACT]]
+// CHECK:             %[[ABS:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[EXTRACT]]
 // CHECK:             %[[COLLAPSE:.*]] = tensor.collapse_shape %[[ABS]]
-// CHECK:             %[[EXP:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<log> ins(%[[COLLAPSE]]
+// CHECK:             %[[EXP:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[COLLAPSE]]
 func.func @bubble_up_extract_slice_through_collapse_shape_with_collapse_producer(%0: tensor<1x8x1800x32xf32>) -> tensor<8x1800x32xf32> {
   %empty1 = tensor.empty() : tensor<1x8x1800x32xf32>
-  %abs = linalg.copy ins(%0 : tensor<1x8x1800x32xf32>) outs(%empty1 : tensor<1x8x1800x32xf32>) -> tensor<1x8x1800x32xf32>
+  %abs = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%0 : tensor<1x8x1800x32xf32>) outs(%empty1 : tensor<1x8x1800x32xf32>) -> tensor<1x8x1800x32xf32>
   %expand = tensor.collapse_shape %abs [[0, 1], [2], [3]] : tensor<1x8x1800x32xf32> into tensor<8x1800x32xf32>
   %empty2 = tensor.empty() : tensor<8x1800x32xf32>
-  %exp = linalg.elementwise kind=#linalg.elementwise_kind<log> ins(%expand : tensor<8x1800x32xf32>) outs(%empty2 : tensor<8x1800x32xf32>) -> tensor<8x1800x32xf32>
+  %exp = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%expand : tensor<8x1800x32xf32>) outs(%empty2 : tensor<8x1800x32xf32>) -> tensor<8x1800x32xf32>
   return %exp : tensor<8x1800x32xf32>
 }
 
 module attributes {transform.with_named_sequence} {
   transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-    %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<exp>} in %arg0 : (!transform.any_op) -> !transform.any_op
     %transformed, %loops:1 = transform.structured.fuse %0 tile_sizes [1, 0, 0] interchange [0, 1, 2] apply_cleanup :
       (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">)
     transform.yield
@@ -677,7 +677,7 @@ module attributes {transform.with_named_sequence} {
 //       CHECK:   scf.for
 //       CHECK:     tensor.extract_slice %{{.*}} [2] [1] : tensor<4xf32> to tensor<2xf32>
 //       CHECK:     linalg.generic
-//       CHECK:     linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//       CHECK:     linalg.elementwise kind=#linalg.elementwise_kind<exp>
 func.func @fuse_producer_semi_affine_aligned(%arg0: tensor<12xf32>, %scale: tensor<4xf32>, %init: tensor<12xf32>, %out: tensor<12xf32>) -> tensor<12xf32> {
   %0 = linalg.generic {indexing_maps = [#id, #floordiv3, #id], iterator_types = ["parallel"]}
     ins(%arg0, %scale : tensor<12xf32>, tensor<4xf32>) outs(%init : tensor<12xf32>) {
@@ -685,7 +685,7 @@ func.func @fuse_producer_semi_affine_aligned(%arg0: tensor<12xf32>, %scale: tens
     %m = arith.addf %a, %s : f32
     linalg.yield %m : f32
   } -> tensor<12xf32>
-  %1 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%0 : tensor<12xf32>) outs(%out : tensor<12xf32>) -> tensor<12xf32>
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%0 : tensor<12xf32>) outs(%out : tensor<12xf32>) -> tensor<12xf32>
   return %1 : tensor<12xf32>
 }
 
@@ -713,7 +713,7 @@ func.func @negative_fuse_producer_semi_affine_misaligned(%arg0: tensor<12xf32>,
     %m = arith.addf %a, %s : f32
     linalg.yield %m : f32
   } -> tensor<12xf32>
-  %1 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%0 : tensor<12xf32>) outs(%out : tensor<12xf32>) -> tensor<12xf32>
+  %1 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%0 : tensor<12xf32>) outs(%out : tensor<12xf32>) -> tensor<12xf32>
   return %1 : tensor<12xf32>
 }
 
diff --git a/mlir/test/Dialect/Linalg/transform-op-generalize.mlir b/mlir/test/Dialect/Linalg/transform-op-generalize.mlir
index 804d3eef4dc3c..957212d050837 100644
--- a/mlir/test/Dialect/Linalg/transform-op-generalize.mlir
+++ b/mlir/test/Dialect/Linalg/transform-op-generalize.mlir
@@ -3,9 +3,9 @@
 // CHECK-LABEL: func.func @generalize_unary
 func.func @generalize_unary(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<?x?xf32> {
 
-  // CHECK-NOT:   linalg.elementwise kind=#linalg.elementwise_kind<abs>
+  // CHECK-NOT:   linalg.elementwise kind=#linalg.elementwise_kind<exp>
   //     CHECK:   linalg.generic
-  %0 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%arg0 : tensor<?x?xf32>)
+  %0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
                              outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
   return %0 : tensor<?x?xf32>
 }
diff --git a/mlir/test/Dialect/SCF/canonicalize.mlir b/mlir/test/Dialect/SCF/canonicalize.mlir
index 37a337305159f..a7f11aae3461f 100644
--- a/mlir/test/Dialect/SCF/canonicalize.mlir
+++ b/mlir/test/Dialect/SCF/canonicalize.mlir
@@ -2170,7 +2170,7 @@ module {
       %4 = affine.min #map2(%arg3)[%dim, %arg0]
       %extracted_slice0 = tensor.extract_slice %arg4[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
       %extracted_slice1 = tensor.extract_slice %arg5[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
-      %5 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%extracted_slice0 : tensor<?xf32>) outs(%extracted_slice1 : tensor<?xf32>) -> tensor<?xf32>
+      %5 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%extracted_slice0 : tensor<?xf32>) outs(%extracted_slice1 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %5 into %arg5[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
       }
@@ -2184,7 +2184,7 @@ module {
 //  CHECK-SAME:                       shared_outs(%[[ITER_ARG_5:.*]] = %[[ARG2]]) -> (tensor<?xf32>) {
 //       CHECK:      %[[OPERAND0:.*]] = tensor.extract_slice %[[ARG1]]
 //       CHECK:      %[[OPERAND1:.*]] = tensor.extract_slice %[[ITER_ARG_5]]
-//       CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[OPERAND0]] : tensor<?xf32>) outs(%[[OPERAND1]] : tensor<?xf32>) -> tensor<?xf32>
+//       CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[OPERAND0]] : tensor<?xf32>) outs(%[[OPERAND1]] : tensor<?xf32>) -> tensor<?xf32>
 //       CHECK:      scf.forall.in_parallel {
 //  CHECK-NEXT:         tensor.parallel_insert_slice %[[ELEM]] into %[[ITER_ARG_5]]
 //  CHECK-NEXT:      }
@@ -2210,7 +2210,7 @@ module {
       %extracted_slice_0 = tensor.extract_slice %arg6[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
       %extracted_slice_1 = tensor.extract_slice %arg7[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
       %extracted_slice_2 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>
-      %5 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%extracted_slice : tensor<?xf32>) outs(%extracted_slice_1 : tensor<?xf32>) -> tensor<?xf32>
+      %5 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%extracted_slice : tensor<?xf32>) outs(%extracted_slice_1 : tensor<?xf32>) -> tensor<?xf32>
       scf.forall.in_parallel {
         tensor.parallel_insert_slice %5 into %arg6[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
         tensor.parallel_insert_slice %extracted_slice into %arg5[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>
@@ -2227,7 +2227,7 @@ module {
 //  CHECK-SAME:                       shared_outs(%[[ITER_ARG_6:.*]] = %[[ARG2]]) -> (tensor<?xf32>) {
 //       CHECK:      %[[OPERAND0:.*]] = tensor.extract_slice %[[ARG1]]
 //       CHECK:      %[[OPERAND1:.*]] = tensor.extract_slice %[[ARG3]]
-//       CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%[[OPERAND0]] : tensor<?xf32>) outs(%[[OPERAND1]] : tensor<?xf32>) -> tensor<?xf32>
+//       CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%[[OPERAND0]] : tensor<?xf32>) outs(%[[OPERAND1]] : tensor<?xf32>) -> tensor<?xf32>
 //       CHECK:      scf.forall.in_parallel {
 //  CHECK-NEXT:         tensor.parallel_insert_slice %[[ELEM]] into %[[ITER_ARG_6]]
 //  CHECK-NEXT:      }
diff --git a/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer-using-slices.mlir b/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer-using-slices.mlir
index 64de801ac6286..130c1ae383418 100644
--- a/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer-using-slices.mlir
+++ b/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer-using-slices.mlir
@@ -459,7 +459,7 @@ func.func @fuse_pack_consumer_if_single_iteration(%arg0: tensor<4x4xf32>) -> ten
     %3 = affine.min #map(%arg1)
     %extracted_slice = tensor.extract_slice %arg0[%arg1, 0] [%3, 4] [1, 1] : tensor<4x4xf32> to tensor<?x4xf32>
     %extracted_slice_0 = tensor.extract_slice %arg2[%arg1, 0] [%3, 4] [1, 1] : tensor<4x4xf32> to tensor<?x4xf32>
-    %4 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%extracted_slice : tensor<?x4xf32>) outs(%extracted_slice_0 : tensor<?x4xf32>) -> tensor<?x4xf32>
+    %4 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%extracted_slice : tensor<?x4xf32>) outs(%extracted_slice_0 : tensor<?x4xf32>) -> tensor<?x4xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %4 into %arg2[%arg1, 0] [%3, 4] [1, 1] : tensor<?x4xf32> into tensor<4x4xf32>
     }
@@ -488,7 +488,7 @@ module attributes {transform.with_named_sequence} {
 //  CHECK-DAG:      %[[SIZE:.+]] = affine.min #[[MAP]](%[[IV]])
 //  CHECK-DAG:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][%[[IV]], 0] [%[[SIZE]], 4] [1, 1]
 //  CHECK-DAG:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[ELEM_OUT_ARG]][%[[IV]], 0] [%[[SIZE]], 4] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[TILED_PACK_DEST:.*]] = tensor.extract_slice %[[PACK_OUT_ARG]][%[[IV]], 0, 0, 0] [1, 4, 16, 1] [1, 1, 1, 1]
@@ -506,7 +506,7 @@ func.func @fuse_perfect_tiling_pack_consumer_with_outer_dims_perm(%arg0: tensor<
   %0 = scf.forall (%arg3) = (0) to (32) step (16) shared_outs(%arg4 = %arg1) -> (tensor<64x32xf32>) {
     %src = tensor.extract_slice %arg0[0, %arg3] [64, 16] [1, 1] : tensor<64x32xf32> to tensor<64x16xf32>
     %dest = tensor.extract_slice %arg4[0, %arg3] [64, 16] [1, 1] : tensor<64x32xf32> to tensor<64x16xf32>
-    %1 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
+    %1 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %1 into %arg4[0, %arg3] [64, 16] [1, 1] : tensor<64x16xf32> into tensor<64x32xf32>
     }
@@ -532,7 +532,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:      shared_outs(%[[FIRST_OUT_ARG:.*]] = %[[ARG1]], %[[PACK_OUT_ARG:.*]] = %[[ARG2]])
 //      CHECK:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][0, %[[IV]]] [64, 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[FIRST_OUT_ARG]][0, %[[IV]]] [64, 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[PACK_RESULT_OFFSET:.*]] = affine.apply #[[PACK_RESULT_MAP]](%[[IV]])
@@ -555,7 +555,7 @@ func.func @fuse_pack_consumer_with_no_pad_dynamic_dim(%arg0: tensor<64x?xf32>, %
   %0 = scf.forall (%arg2) = (0) to (%d1) step (16) shared_outs(%arg3 = %arg1) -> (tensor<64x?xf32>) {
     %src = tensor.extract_slice %arg0[0, %arg2] [64, 16] [1, 1] : tensor<64x?xf32> to tensor<64x16xf32>
     %dest = tensor.extract_slice %arg3[0, %arg2] [64, 16] [1, 1] : tensor<64x?xf32> to tensor<64x16xf32>
-    %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
+    %2 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %2 into %arg3[0, %arg2] [64, 16] [1, 1] : tensor<64x16xf32> into tensor<64x?xf32>
     }
@@ -581,7 +581,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:      shared_outs(%[[FIRST_OUT_ARG:.*]] = %[[ARG1]], %[[PACK_OUT_ARG:.*]] = %[[ARG2]])
 //      CHECK:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][0, %[[IV]]] [64, 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[FIRST_OUT_ARG]][0, %[[IV]]] [64, 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[PACK_RESULT_OFFSET:.*]] = affine.apply #[[PACK_RESULT_MAP]](%[[IV]])
@@ -603,7 +603,7 @@ func.func @fuse_pack_consumer_with_padding_semantics(%arg0: tensor<64x32xf32>, %
     %size = affine.min affine_map<(d0) -> (-d0 + 64, 15)>(%arg2)
     %src = tensor.extract_slice %arg0[%arg2, %arg3] [%size, 16] [1, 1] : tensor<64x32xf32> to tensor<?x16xf32>
     %dest = tensor.extract_slice %arg4[%arg2, %arg3] [%size, 16] [1, 1] : tensor<64x32xf32> to tensor<?x16xf32>
-    %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<?x16xf32>) outs(%dest : tensor<?x16xf32>) -> tensor<?x16xf32>
+    %2 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%src : tensor<?x16xf32>) outs(%dest : tensor<?x16xf32>) -> tensor<?x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %2 into %arg4[%arg2, %arg3] [%size, 16] [1, 1] : tensor<?x16xf32> into tensor<64x32xf32>
     }
@@ -638,7 +638,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:        [%[[I]], %[[J]]] [%[[SIZE]], 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[ELEM_OUT]]
 // CHECK-SAME:        [%[[I]], %[[J]]] [%[[SIZE]], 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[D0_OFFSET:.*]] = affine.apply #[[MAP1]](%[[I]])
@@ -710,7 +710,7 @@ module {
         scf.yield %insert_slice : tensor<256x256xf32>
     }
     %4 = linalg.mul ins(%1, %arg2 : tensor<256x256xf32>, tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
-    %5 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%1 : tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
+    %5 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%1 : tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
     return %4, %5 : tensor<256x256xf32>, tensor<256x256xf32>
   }
 }
@@ -742,7 +742,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:                outs(%[[ADD_OUT_SLICE]] :
 //      CHECK:          %[[INSERT_ADD:.*]] = tensor.insert_slice %[[TILED_ADD_OUT]] into %[[FIRST_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
 //      CHECK:          %[[EXP_OUT_SLICE:.*]] = tensor.extract_slice %[[SECOND_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
-//      CHECK:          %[[TILED_EXP_OUT:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//      CHECK:          %[[TILED_EXP_OUT:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME:                ins(%[[TILED_ADD_OUT]] :
 // CHECK-SAME:                outs(%[[EXP_OUT_SLICE]] :
 //      CHECK:          %[[MUL_INS2_SLICE:.*]] = tensor.extract_slice %[[ARG2]][%[[IV1]], 0] [64, 256] [1, 1]
diff --git a/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer.mlir b/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer.mlir
index eae7d86873cb5..f7deb6a05e820 100644
--- a/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer.mlir
+++ b/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer.mlir
@@ -503,7 +503,7 @@ func.func @fuse_pack_consumer_if_single_iteration(%arg0: tensor<4x4xf32>) -> ten
     %3 = affine.min #map(%arg1)
     %extracted_slice = tensor.extract_slice %arg0[%arg1, 0] [%3, 4] [1, 1] : tensor<4x4xf32> to tensor<?x4xf32>
     %extracted_slice_0 = tensor.extract_slice %arg2[%arg1, 0] [%3, 4] [1, 1] : tensor<4x4xf32> to tensor<?x4xf32>
-    %4 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%extracted_slice : tensor<?x4xf32>) outs(%extracted_slice_0 : tensor<?x4xf32>) -> tensor<?x4xf32>
+    %4 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%extracted_slice : tensor<?x4xf32>) outs(%extracted_slice_0 : tensor<?x4xf32>) -> tensor<?x4xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %4 into %arg2[%arg1, 0] [%3, 4] [1, 1] : tensor<?x4xf32> into tensor<4x4xf32>
     }
@@ -531,7 +531,7 @@ module attributes {transform.with_named_sequence} {
 //  CHECK-DAG:      %[[SIZE:.+]] = affine.min affine_map<(d0) -> (-d0 + 4, 16)>(%[[IV]])
 //  CHECK-DAG:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][%[[IV]], 0] [%[[SIZE]], 4] [1, 1]
 //  CHECK-DAG:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[ELEM_OUT_ARG]][%[[IV]], 0] [%[[SIZE]], 4] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[TILED_PACK_DEST:.*]] = tensor.extract_slice %[[PACK_OUT_ARG]][%[[IV]], 0, 0, 0] [1, 4, 16, 1] [1, 1, 1, 1]
@@ -549,7 +549,7 @@ func.func @fuse_perfect_tiling_pack_consumer_with_outer_dims_perm(%arg0: tensor<
   %0 = scf.forall (%arg3) = (0) to (32) step (16) shared_outs(%arg4 = %arg1) -> (tensor<64x32xf32>) {
     %src = tensor.extract_slice %arg0[0, %arg3] [64, 16] [1, 1] : tensor<64x32xf32> to tensor<64x16xf32>
     %dest = tensor.extract_slice %arg4[0, %arg3] [64, 16] [1, 1] : tensor<64x32xf32> to tensor<64x16xf32>
-    %1 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
+    %1 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %1 into %arg4[0, %arg3] [64, 16] [1, 1] : tensor<64x16xf32> into tensor<64x32xf32>
     }
@@ -574,7 +574,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:      shared_outs(%[[FIRST_OUT_ARG:.*]] = %[[ARG1]], %[[PACK_OUT_ARG:.*]] = %[[ARG2]])
 //      CHECK:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][0, %[[IV]]] [64, 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[FIRST_OUT_ARG]][0, %[[IV]]] [64, 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[PACK_RESULT_OFFSET:.*]] = affine.apply affine_map<(d0) -> (d0 floordiv 16)>(%[[IV]])
@@ -597,7 +597,7 @@ func.func @fuse_pack_consumer_with_no_pad_dynamic_dim(%arg0: tensor<64x?xf32>, %
   %0 = scf.forall (%arg2) = (0) to (%d1) step (16) shared_outs(%arg3 = %arg1) -> (tensor<64x?xf32>) {
     %src = tensor.extract_slice %arg0[0, %arg2] [64, 16] [1, 1] : tensor<64x?xf32> to tensor<64x16xf32>
     %dest = tensor.extract_slice %arg3[0, %arg2] [64, 16] [1, 1] : tensor<64x?xf32> to tensor<64x16xf32>
-    %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
+    %2 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%src : tensor<64x16xf32>) outs(%dest : tensor<64x16xf32>) -> tensor<64x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %2 into %arg3[0, %arg2] [64, 16] [1, 1] : tensor<64x16xf32> into tensor<64x?xf32>
     }
@@ -622,7 +622,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:      shared_outs(%[[FIRST_OUT_ARG:.*]] = %[[ARG1]], %[[PACK_OUT_ARG:.*]] = %[[ARG2]])
 //      CHECK:      %[[ELEM_SRC:.*]] = tensor.extract_slice %[[ARG0]][0, %[[IV]]] [64, 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[FIRST_OUT_ARG]][0, %[[IV]]] [64, 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[PACK_RESULT_OFFSET:.*]] = affine.apply affine_map<(d0) -> (d0 floordiv 16)>(%[[IV]])
@@ -644,7 +644,7 @@ func.func @fuse_pack_consumer_with_padding_semantics(%arg0: tensor<64x32xf32>, %
     %size = affine.min affine_map<(d0) -> (-d0 + 64, 15)>(%arg2)
     %src = tensor.extract_slice %arg0[%arg2, %arg3] [%size, 16] [1, 1] : tensor<64x32xf32> to tensor<?x16xf32>
     %dest = tensor.extract_slice %arg4[%arg2, %arg3] [%size, 16] [1, 1] : tensor<64x32xf32> to tensor<?x16xf32>
-    %2 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%src : tensor<?x16xf32>) outs(%dest : tensor<?x16xf32>) -> tensor<?x16xf32>
+    %2 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%src : tensor<?x16xf32>) outs(%dest : tensor<?x16xf32>) -> tensor<?x16xf32>
     scf.forall.in_parallel {
       tensor.parallel_insert_slice %2 into %arg4[%arg2, %arg3] [%size, 16] [1, 1] : tensor<?x16xf32> into tensor<64x32xf32>
     }
@@ -675,7 +675,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:        [%[[I]], %[[J]]] [%[[SIZE]], 16] [1, 1]
 //      CHECK:      %[[ELEM_DEST:.*]] = tensor.extract_slice %[[ELEM_OUT]]
 // CHECK-SAME:        [%[[I]], %[[J]]] [%[[SIZE]], 16] [1, 1]
-//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//      CHECK:      %[[ELEM:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME:        ins(%[[ELEM_SRC]]
 // CHECK-SAME:        outs(%[[ELEM_DEST]]
 //  CHECK-DAG:      %[[D0_OFFSET:.*]] = affine.apply affine_map<(d0) -> (d0 floordiv 3)>(%[[I]])
@@ -748,7 +748,7 @@ module {
         scf.yield %insert_slice : tensor<256x256xf32>
     }
     %4 = linalg.mul ins(%1, %arg2 : tensor<256x256xf32>, tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
-    %5 = linalg.elementwise kind=#linalg.elementwise_kind<abs> ins(%1 : tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
+    %5 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%1 : tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
     return %4, %5 : tensor<256x256xf32>, tensor<256x256xf32>
   }
 }
@@ -789,7 +789,7 @@ module attributes {transform.with_named_sequence} {
 // CHECK-SAME:                ins(%[[TILED_ADD_OUT]], %[[MUL_INS2_SLICE]] :
 // CHECK-SAME:                outs(%[[MUL_OUT_SLICE]] :
 //      CHECK:          %[[EXP_OUT_SLICE:.*]] = tensor.extract_slice %[[THIRD_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
-//      CHECK:          %[[TILED_EXP_OUT:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<abs>
+//      CHECK:          %[[TILED_EXP_OUT:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<exp>
 // CHECK-SAME:                ins(%[[TILED_ADD_OUT]] :
 // CHECK-SAME:                outs(%[[EXP_OUT_SLICE]] :
 //      CHECK:          %[[INSERT_MUL:.*]] = tensor.insert_slice %[[TILED_MUL_OUT]] into %[[SECOND_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]



More information about the Mlir-commits mailing list