[llvm-branch-commits] [mlir] [MLIR][Linalg] Remove binary named ops (PR #220912)
Renato Golin via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Sep 4 09:18:02 PDT 2026
https://github.com/rengolin updated https://github.com/llvm/llvm-project/pull/220912
>From 278ea912a362d4457cb4a5153234528e1cd9c458 Mon Sep 17 00:00:00 2001
From: rengolin <rengolin at systemcall.eu>
Date: Wed, 2 Sep 2026 08:10:37 -0700
Subject: [PATCH] [MLIR][Linalg] Remove binary named ops
Remove ops, change tests to elementwise to continue working as is.
Depends on the unary removal branch.
Ref:
https://discourse.llvm.org/t/rfc-update-semantics-of-linalg-named-operations-unary-binary-ternary/91531
---
.../Linalg/IR/LinalgNamedStructuredOps.yaml | 395 ------------------
.../Linalg/Transforms/CategoryToNamedOp.cpp | 16 -
.../Linalg/Transforms/FoldAddIntoDest.cpp | 26 +-
.../Linalg/Transforms/NamedToElementwise.cpp | 12 -
.../Dialect/Linalg/Transforms/Specialize.cpp | 38 +-
.../linalg/opdsl/ops/core_named_ops.py | 155 -------
.../Dialect/Arith/sharding-propagation.mlir | 11 +-
.../Dialect/Linalg/block-pack-matmul.mlir | 4 +-
...ic-by-unfolding-projected-permutation.mlir | 6 +-
.../elementwise/named-to-elementwise.mlir | 26 --
.../Dialect/Linalg/fold-add-into-dest.mlir | 48 +--
.../Dialect/Linalg/generalize-named-ops.mlir | 202 ---------
mlir/test/Dialect/Linalg/invalid.mlir | 10 -
.../linalg-morph-elementwise-to-named.mlir | 30 +-
.../Linalg/linalg-morph-multi-step.mlir | 135 ------
mlir/test/Dialect/Linalg/named-ops-fail.mlir | 128 ------
mlir/test/Dialect/Linalg/named-ops.mlir | 272 ------------
mlir/test/Dialect/Linalg/reshape_fusion.mlir | 4 +-
.../roundtrip-morphism-linalg-named-ops.mlir | 160 -------
.../Linalg/specialize-generic-ops.mlir | 138 ++----
.../Dialect/Linalg/transform-op-fuse.mlir | 94 ++---
...-rewrite-in-destination-passing-style.mlir | 6 +-
...ansform-op-specialize-elemwise-binary.mlir | 86 +---
.../SparseTensor/encoding_with_symbols.mlir | 4 +-
.../SparseTensor/external_after_codegen.mlir | 2 +-
.../Transform/test-promote-tensors.mlir | 12 +-
.../TilingInterface/query-fusability.mlir | 12 +-
.../tile-and-fuse-consumer-using-slices.mlir | 28 +-
.../tile-and-fuse-consumer.mlir | 34 +-
.../tile-fuse-and-yield-using-interface.mlir | 6 +-
30 files changed, 235 insertions(+), 1865 deletions(-)
delete mode 100644 mlir/test/Dialect/Linalg/linalg-morph-multi-step.mlir
diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml b/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml
index 5514ba3afcf37..58ef08fee0463 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml
+++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml
@@ -44,401 +44,6 @@ structured_op: !LinalgStructuredOpConfig
- !ScalarExpression
scalar_arg: I
--- !LinalgOpConfig
-metadata: !LinalgOpMetadata
- name: add
- cpp_class_name: AddOp
- doc: |-
- Adds two tensors elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.add` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
-structured_op: !LinalgStructuredOpConfig
- args:
- - !LinalgOperandDefConfig
- name: lhs
- kind: input_tensor
- type_var: T1
- shape_map: affine_map<() -> ()>
- - !LinalgOperandDefConfig
- name: rhs
- 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<() -> ()>
- - affine_map<() -> ()>
- iterator_types: []
- assignments:
- - !ScalarAssign
- arg: O
- value: !ScalarExpression
- scalar_fn:
- kind: binary
- fn_name: add
- operands:
- - !ScalarExpression
- scalar_arg: lhs
- - !ScalarExpression
- scalar_arg: rhs
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
- name: sub
- cpp_class_name: SubOp
- doc: |-
- Subtracts two tensors elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.sub` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
-structured_op: !LinalgStructuredOpConfig
- args:
- - !LinalgOperandDefConfig
- name: lhs
- kind: input_tensor
- type_var: T1
- shape_map: affine_map<() -> ()>
- - !LinalgOperandDefConfig
- name: rhs
- 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<() -> ()>
- - affine_map<() -> ()>
- iterator_types: []
- assignments:
- - !ScalarAssign
- arg: O
- value: !ScalarExpression
- scalar_fn:
- kind: binary
- fn_name: sub
- operands:
- - !ScalarExpression
- scalar_arg: lhs
- - !ScalarExpression
- scalar_arg: rhs
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
- name: mul
- cpp_class_name: MulOp
- doc: |-
- Multiplies two tensors elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.mul` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
-structured_op: !LinalgStructuredOpConfig
- args:
- - !LinalgOperandDefConfig
- name: lhs
- kind: input_tensor
- type_var: T1
- shape_map: affine_map<() -> ()>
- - !LinalgOperandDefConfig
- name: rhs
- 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<() -> ()>
- - affine_map<() -> ()>
- iterator_types: []
- assignments:
- - !ScalarAssign
- arg: O
- value: !ScalarExpression
- scalar_fn:
- kind: binary
- fn_name: mul
- operands:
- - !ScalarExpression
- scalar_arg: lhs
- - !ScalarExpression
- scalar_arg: rhs
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
- name: div
- cpp_class_name: DivOp
- doc: |-
- Divides the first tensor by the second tensor, elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.div` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
-structured_op: !LinalgStructuredOpConfig
- args:
- - !LinalgOperandDefConfig
- name: lhs
- kind: input_tensor
- type_var: T1
- shape_map: affine_map<() -> ()>
- - !LinalgOperandDefConfig
- name: rhs
- 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<() -> ()>
- - affine_map<() -> ()>
- iterator_types: []
- assignments:
- - !ScalarAssign
- arg: O
- value: !ScalarExpression
- scalar_fn:
- kind: binary
- fn_name: div
- operands:
- - !ScalarExpression
- scalar_arg: lhs
- - !ScalarExpression
- scalar_arg: rhs
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
- name: div_unsigned
- cpp_class_name: DivUnsignedOp
- doc: |-
- Divides the first tensor by the second tensor, elementwise. For integer
- types, performs an unsigned division.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.div` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
-structured_op: !LinalgStructuredOpConfig
- args:
- - !LinalgOperandDefConfig
- name: lhs
- kind: input_tensor
- type_var: T1
- shape_map: affine_map<() -> ()>
- - !LinalgOperandDefConfig
- name: rhs
- 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<() -> ()>
- - affine_map<() -> ()>
- iterator_types: []
- assignments:
- - !ScalarAssign
- arg: O
- value: !ScalarExpression
- scalar_fn:
- kind: binary
- fn_name: div_unsigned
- operands:
- - !ScalarExpression
- scalar_arg: lhs
- - !ScalarExpression
- scalar_arg: rhs
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
- name: max
- cpp_class_name: MaxOp
- doc: |-
- Takes the max (signed) between two inputs, elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.max` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
-structured_op: !LinalgStructuredOpConfig
- args:
- - !LinalgOperandDefConfig
- name: lhs
- kind: input_tensor
- type_var: T1
- shape_map: affine_map<() -> ()>
- - !LinalgOperandDefConfig
- name: rhs
- 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<() -> ()>
- - affine_map<() -> ()>
- iterator_types: []
- assignments:
- - !ScalarAssign
- arg: O
- value: !ScalarExpression
- scalar_fn:
- kind: binary
- fn_name: max_signed
- operands:
- - !ScalarExpression
- scalar_arg: lhs
- - !ScalarExpression
- scalar_arg: rhs
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
- name: min
- cpp_class_name: MinOp
- doc: |-
- Takes the min (signed) between two inputs, elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.min` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
-structured_op: !LinalgStructuredOpConfig
- args:
- - !LinalgOperandDefConfig
- name: lhs
- kind: input_tensor
- type_var: T1
- shape_map: affine_map<() -> ()>
- - !LinalgOperandDefConfig
- name: rhs
- 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<() -> ()>
- - affine_map<() -> ()>
- iterator_types: []
- assignments:
- - !ScalarAssign
- arg: O
- value: !ScalarExpression
- scalar_fn:
- kind: binary
- fn_name: min_signed
- operands:
- - !ScalarExpression
- scalar_arg: lhs
- - !ScalarExpression
- scalar_arg: rhs
---- !LinalgOpConfig
-metadata: !LinalgOpMetadata
- name: powf
- cpp_class_name: PowFOp
- doc: |-
- Takes the powf(lhs, rhs) between two inputs, elementwise. For powf(arg, 2) use `linalg.elementwise kind=square`.
-
- Only applies to floating point values.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.powf` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
-structured_op: !LinalgStructuredOpConfig
- args:
- - !LinalgOperandDefConfig
- name: lhs
- kind: input_tensor
- type_var: T1
- shape_map: affine_map<() -> ()>
- - !LinalgOperandDefConfig
- name: rhs
- 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<() -> ()>
- - affine_map<() -> ()>
- iterator_types: []
- assignments:
- - !ScalarAssign
- arg: O
- value: !ScalarExpression
- scalar_fn:
- kind: binary
- fn_name: powf
- operands:
- - !ScalarExpression
- scalar_arg: lhs
- - !ScalarExpression
- scalar_arg: rhs
---- !LinalgOpConfig
metadata: !LinalgOpMetadata
name: select
cpp_class_name: SelectOp
diff --git a/mlir/lib/Dialect/Linalg/Transforms/CategoryToNamedOp.cpp b/mlir/lib/Dialect/Linalg/Transforms/CategoryToNamedOp.cpp
index 711069caff7c4..4b36808b8a458 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/CategoryToNamedOp.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/CategoryToNamedOp.cpp
@@ -46,22 +46,6 @@ struct ElementwiseToNamedPattern : public OpRewritePattern<ElementwiseOp> {
};
switch (op.getKind()) {
- case ElementwiseKind::add:
- return replaceWith(AddOp{});
- case ElementwiseKind::sub:
- return replaceWith(SubOp{});
- case ElementwiseKind::mul:
- return replaceWith(MulOp{});
- case ElementwiseKind::div:
- return replaceWith(DivOp{});
- case ElementwiseKind::div_unsigned:
- return replaceWith(DivUnsignedOp{});
- case ElementwiseKind::max_signed:
- return replaceWith(MaxOp{});
- case ElementwiseKind::min_signed:
- return replaceWith(MinOp{});
- case ElementwiseKind::powf:
- return replaceWith(PowFOp{});
case ElementwiseKind::select:
return replaceWith(SelectOp{});
default:
diff --git a/mlir/lib/Dialect/Linalg/Transforms/FoldAddIntoDest.cpp b/mlir/lib/Dialect/Linalg/Transforms/FoldAddIntoDest.cpp
index 7a720073cfdaa..1e9abf9168589 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/FoldAddIntoDest.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/FoldAddIntoDest.cpp
@@ -35,9 +35,10 @@ static bool isDefinedAsZero(Value val) {
.Default([&](auto) { return false; });
}
-/// Replace a linalg.add with one operand the single user of a contraction,
-/// which has a zero-filled, "identity-mapped" destination and is dominated by
-/// the `other` operand, by the contraction with `other` as its dest.
+/// Replace a linalg.elementwise kind=add with one operand the single user of a
+/// contraction, which has a zero-filled, "identity-mapped" destination and is
+/// dominated by the `other` operand, by the contraction with `other` as its
+/// dest.
///
/// As an example, the following pseudo-code will be rewritten
/// %cst = arith.constant 0.000000e+00
@@ -47,7 +48,7 @@ static bool isDefinedAsZero(Value val) {
/// %empty2 = tensor.empty()
/// %zeroed2 = linalg.fill ins(%cst : f32) outs(%empty2 : !type) -> !type
/// %F = linalg.matmul ins(%D, %E) outs(%zeroed2)
-/// %out = linalg.add ins(%C, %F) outs(%empty)
+/// %out = linalg.elementwise kind=add ins(%C, %F) outs(%empty)
/// to:
/// %cst = arith.constant 0.000000e+00
/// %empty = tensor.empty()
@@ -55,11 +56,15 @@ static bool isDefinedAsZero(Value val) {
/// %C = linalg.matmul ins(%A, %B) outs(%zeroed)
/// %out = linalg.matmul ins(%D, %E) outs(%C)
///
-struct FoldAddIntoDest final : public OpRewritePattern<linalg::AddOp> {
- using OpRewritePattern<linalg::AddOp>::OpRewritePattern;
+struct FoldAddIntoDest final : public OpRewritePattern<linalg::ElementwiseOp> {
+ using OpRewritePattern<linalg::ElementwiseOp>::OpRewritePattern;
- LogicalResult matchAndRewrite(linalg::AddOp addOp,
+ LogicalResult matchAndRewrite(linalg::ElementwiseOp addOp,
PatternRewriter &rewriter) const override {
+ // Pattern only applies on a binary elementwise add.
+ if (addOp.getKind() != linalg::ElementwiseKind::add)
+ return failure();
+
// For now, pattern only applies on tensor types (memref support is TODO).
if (!addOp.hasPureTensorSemantics())
return failure();
@@ -90,8 +95,9 @@ struct FoldAddIntoDest final : public OpRewritePattern<linalg::AddOp> {
}
if (!dominatingOperand || !dominatedOp)
return failure();
- // NB: As linalg.add's generalisation ignores the out argument in its
- // region there is no need to perform checks on addOp's out argument.
+ // NB: As the elementwise add's generalisation ignores the out argument in
+ // its region there is no need to perform checks on addOp's out
+ // argument.
}
// When dominated op is a contraction we know it accumulates on its out arg.
@@ -111,7 +117,7 @@ struct FoldAddIntoDest final : public OpRewritePattern<linalg::AddOp> {
if (!dominatedOp->getResult(0).hasOneUse())
return rewriter.notifyMatchFailure(
dominatedOp,
- "expected linalg.add to be single user of contraction's result");
+ "expected elementwise add to be single user of contraction's result");
// As `dominatedOp` was already accumulating on its out argument, it is only
// safe to no longer use its current out arg when it is the additive ident.
diff --git a/mlir/lib/Dialect/Linalg/Transforms/NamedToElementwise.cpp b/mlir/lib/Dialect/Linalg/Transforms/NamedToElementwise.cpp
index b2687cb4dc87b..d4411d0f7d80a 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/NamedToElementwise.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/NamedToElementwise.cpp
@@ -29,12 +29,6 @@ namespace {
ElementwiseKind getKind(Operation *op) {
return llvm::TypeSwitch<Operation *, ElementwiseKind>(op)
.Case([](SelectOp) { return ElementwiseKind::select; })
- .Case([](AddOp) { return ElementwiseKind::add; })
- .Case([](SubOp) { return ElementwiseKind::sub; })
- .Case([](MulOp) { return ElementwiseKind::mul; })
- .Case([](DivOp) { return ElementwiseKind::div; })
- .Case([](DivUnsignedOp) { return ElementwiseKind::div_unsigned; })
- .Case([](PowFOp) { return ElementwiseKind::powf; })
.DefaultUnreachable("unhandled case in named to elementwise");
}
@@ -60,10 +54,4 @@ struct NamedToElementwisePattern : public OpRewritePattern<NamedOpTy> {
void mlir::linalg::populateLinalgNamedToElementwisePatterns(
RewritePatternSet &patterns) {
patterns.add<NamedToElementwisePattern<SelectOp>>(patterns.getContext());
- patterns.add<NamedToElementwisePattern<AddOp>>(patterns.getContext());
- patterns.add<NamedToElementwisePattern<SubOp>>(patterns.getContext());
- patterns.add<NamedToElementwisePattern<MulOp>>(patterns.getContext());
- patterns.add<NamedToElementwisePattern<DivOp>>(patterns.getContext());
- patterns.add<NamedToElementwisePattern<DivUnsignedOp>>(patterns.getContext());
- patterns.add<NamedToElementwisePattern<PowFOp>>(patterns.getContext());
}
diff --git a/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp b/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp
index a063465e1a4c9..0c8e5cd212406 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp
@@ -155,14 +155,14 @@ static FailureOr<LinalgOp> specializeLinalgElementwise(RewriterBase &rewriter,
std::swap(inputs[0], inputs[1]);
LinalgOp newOp;
- if (!emitCategoryOp) {
- using NamedOpTy = decltype(namedOp);
+ using NamedOpTy = decltype(namedOp);
+ // A null named op means the op only has a category form; emit
+ // `linalg.elementwise` regardless of the requested output form.
+ if (!emitCategoryOp && !std::is_null_pointer_v<NamedOpTy>) {
if constexpr (!std::is_null_pointer_v<NamedOpTy>)
newOp = NamedOpTy::create(rewriter, genericOp.getLoc(), inputs,
genericOp.getDpsInits(),
ArrayRef<NamedAttribute>{});
- else
- llvm_unreachable("Missing named op type");
} else {
SmallVector<AffineMap> indexingMaps = genericOp.getIndexingMapsArray();
// Swap indexing maps, too.
@@ -269,31 +269,29 @@ static FailureOr<LinalgOp> specializeLinalgElementwise(RewriterBase &rewriter,
bool allBool = llvm::all_of(op->getOperands(),
[](Value v) { return v.getType().isInteger(1); });
- if (isa<arith::AddIOp, arith::AddFOp, complex::AddOp>(op) ||
+ if (isa<arith::AddFOp, arith::AddIOp, complex::AddOp>(op) ||
(allBool && isa<arith::OrIOp>(op)))
- return replaceOp(AddOp{}, ElementwiseKind::add);
+ return replaceOp(nullptr, ElementwiseKind::add);
if (isa<arith::SubIOp, arith::SubFOp, complex::SubOp>(op))
- return replaceOp(SubOp{}, ElementwiseKind::sub);
+ return replaceOp(nullptr, ElementwiseKind::sub);
if (isa<arith::MulIOp, arith::MulFOp, complex::MulOp>(op) ||
(allBool && isa<arith::AndIOp>(op)))
- return replaceOp(MulOp{}, ElementwiseKind::mul);
+ return replaceOp(nullptr, ElementwiseKind::mul);
if (isa<arith::DivSIOp, arith::DivFOp, complex::DivOp>(op))
- return replaceOp(DivOp{}, ElementwiseKind::div);
+ return replaceOp(nullptr, ElementwiseKind::div);
if (isa<arith::DivUIOp>(op))
- return replaceOp(DivUnsignedOp{}, ElementwiseKind::div_unsigned);
+ return replaceOp(nullptr, ElementwiseKind::div_unsigned);
if (isa<arith::MaxSIOp, arith::MaximumFOp>(op))
- return replaceOp(MaxOp{}, ElementwiseKind::max_signed);
+ return replaceOp(nullptr, ElementwiseKind::max_signed);
if (isa<arith::MinSIOp, arith::MinimumFOp>(op))
- return replaceOp(MinOp{}, ElementwiseKind::min_signed);
- if (emitCategoryOp) {
- // No named ops for unsigned maximum/minimum.
- if (isa<arith::MaxUIOp>(op))
- return replaceOp(nullptr, ElementwiseKind::max_unsigned);
- if (isa<arith::MinUIOp>(op))
- return replaceOp(nullptr, ElementwiseKind::min_unsigned);
- }
+ return replaceOp(nullptr, ElementwiseKind::min_signed);
if (isa<math::PowFOp>(op))
- return replaceOp(PowFOp{}, ElementwiseKind::powf);
+ return replaceOp(nullptr, ElementwiseKind::powf);
+ // No named ops for unsigned maximum/minimum.
+ if (isa<arith::MaxUIOp>(op))
+ return replaceOp(nullptr, ElementwiseKind::max_unsigned);
+ if (isa<arith::MinUIOp>(op))
+ return replaceOp(nullptr, ElementwiseKind::min_unsigned);
return rewriter.notifyMatchFailure(
genericOp,
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 ab80d1d62c662..f64526ee558be 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,161 +21,6 @@ def copy(
O[None] = cast(U, I[None])
- at linalg_structured_op
-def add(
- lhs=TensorDef(T1),
- rhs=TensorDef(T1),
- O=TensorDef(T1, output=True),
-):
- """Adds two tensors elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.add` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
- """
- O[None] = BinaryFn.add(lhs[None], rhs[None])
-
-
- at linalg_structured_op
-def sub(
- lhs=TensorDef(T1),
- rhs=TensorDef(T1),
- O=TensorDef(T1, output=True),
-):
- """Subtracts two tensors elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.sub` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
- """
- O[None] = BinaryFn.sub(lhs[None], rhs[None])
-
-
- at linalg_structured_op
-def mul(
- lhs=TensorDef(T1),
- rhs=TensorDef(T1),
- O=TensorDef(T1, output=True),
-):
- """Multiplies two tensors elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.mul` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
- """
- O[None] = BinaryFn.mul(lhs[None], rhs[None])
-
-
- at linalg_structured_op
-def div(
- lhs=TensorDef(T1),
- rhs=TensorDef(T1),
- O=TensorDef(T1, output=True),
-):
- """Divides the first tensor by the second tensor, elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.div` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
- """
- O[None] = BinaryFn.div(lhs[None], rhs[None])
-
-
- at linalg_structured_op
-def div_unsigned(
- lhs=TensorDef(T1),
- rhs=TensorDef(T1),
- O=TensorDef(T1, output=True),
-):
- """Divides the first tensor by the second tensor, elementwise. For integer
- types, performs an unsigned division.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.div` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
- """
- O[None] = BinaryFn.div_unsigned(lhs[None], rhs[None])
-
-
- at linalg_structured_op
-def max(
- lhs=TensorDef(T1),
- rhs=TensorDef(T1),
- O=TensorDef(T1, output=True),
-):
- """Takes the max (signed) between two inputs, elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.max` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
- """
- O[None] = BinaryFn.max_signed(lhs[None], rhs[None])
-
-
- at linalg_structured_op
-def min(
- lhs=TensorDef(T1),
- rhs=TensorDef(T1),
- O=TensorDef(T1, output=True),
-):
- """Takes the min (signed) between two inputs, elementwise.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.min` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
- """
- O[None] = BinaryFn.min_signed(lhs[None], rhs[None])
-
-
- at linalg_structured_op(op_class_name="PowFOp")
-def powf(
- lhs=TensorDef(T1),
- rhs=TensorDef(T1),
- O=TensorDef(T1, output=True),
-):
- """Takes the powf(lhs, rhs) between two inputs, elementwise. For powf(arg, 2) use `linalg.elementwise kind=square`.
-
- Only applies to floating point values.
-
- The shapes and element types must be identical. The appropriate casts,
- broadcasts and reductions should be done previously to calling this op.
-
- This means reduction/broadcast/element cast semantics is explicit. Further
- passes can take that into account when lowering this code. For example,
- a `linalg.broadcast` + `linalg.powf` sequence can be lowered to a
- `linalg.generic` with different affine maps for the two operands.
- """
- O[None] = BinaryFn.powf(lhs[None], rhs[None])
-
-
@linalg_structured_op
def select(
cond=TensorDef(U),
diff --git a/mlir/test/Dialect/Arith/sharding-propagation.mlir b/mlir/test/Dialect/Arith/sharding-propagation.mlir
index 762620d9dae0c..509c443ff9732 100644
--- a/mlir/test/Dialect/Arith/sharding-propagation.mlir
+++ b/mlir/test/Dialect/Arith/sharding-propagation.mlir
@@ -2,6 +2,9 @@
shard.grid @grid4x4(shape = 4x4)
+#id = affine_map<(d0, d1) -> (d0, d1)>
+#sc = affine_map<(d0, d1) -> ()>
+
// CHECK-LABEL: func.func @test_shard_constant() -> tensor<1024x1024xf32> attributes {llvm.emit_c_interface} {
// CHECK-NEXT: [[vcst:%.*]] = arith.constant dense<0.000000e+00> : tensor<1024x1024xf32>
// CHECK-NEXT: [[vsharding:%.*]] = shard.sharding @grid4x4 split_axes = {{\[\[}}0]] : !shard.sharding
@@ -14,7 +17,7 @@ shard.grid @grid4x4(shape = 4x4)
// CHECK-NEXT: [[vsharded_4:%.*]] = shard.shard [[vsharded]] to [[vsharding_3]] annotate_for_users : tensor<1024x1024xf32>
// CHECK-NEXT: [[vsharding_5:%.*]] = shard.sharding @grid4x4 split_axes = {{\[\[}}0]] : !shard.sharding
// CHECK-NEXT: [[vsharded_6:%.*]] = shard.shard [[vsharded_2]] to [[vsharding_5]] annotate_for_users : tensor<1024x1024xf32>
-// CHECK-NEXT: [[v1:%.*]] = linalg.add ins([[vsharded_4]], [[vcst_0]] : tensor<1024x1024xf32>, f32) outs([[vsharded_6]] : tensor<1024x1024xf32>) -> tensor<1024x1024xf32>
+// CHECK-NEXT: [[v1:%.*]] = linalg.elementwise kind=#linalg.elementwise_kind<add> indexing_maps = {{.*}} ins([[vsharded_4]], [[vcst_0]] : tensor<1024x1024xf32>, f32) outs([[vsharded_6]] : tensor<1024x1024xf32>) -> tensor<1024x1024xf32>
// CHECK-NEXT: [[vsharding_7:%.*]] = shard.sharding @grid4x4 split_axes = {{\[\[}}0]] : !shard.sharding
// CHECK-NEXT: [[vsharded_8:%.*]] = shard.shard [[v1]] to [[vsharding_7]] : tensor<1024x1024xf32>
// CHECK-NEXT: return [[vsharded_8]] : tensor<1024x1024xf32>
@@ -24,7 +27,7 @@ func.func @test_shard_constant() -> (tensor<1024x1024xf32>) attributes {llvm.emi
%sharded_1 = shard.shard %cst_1 to %sharding_1 : tensor<1024x1024xf32>
%ci = arith.constant 43.4e+00 : f32
%o1 = tensor.empty() : tensor<1024x1024xf32>
- %res = linalg.add ins(%sharded_1, %ci : tensor<1024x1024xf32>, f32) outs(%o1 : tensor<1024x1024xf32>) -> tensor<1024x1024xf32>
+ %res = linalg.elementwise kind=#linalg.elementwise_kind<add> indexing_maps = [#id, #sc, #id] ins(%sharded_1, %ci : tensor<1024x1024xf32>, f32) outs(%o1 : tensor<1024x1024xf32>) -> tensor<1024x1024xf32>
return %res : tensor<1024x1024xf32>
}
@@ -40,14 +43,14 @@ func.func @test_shard_constant() -> (tensor<1024x1024xf32>) attributes {llvm.emi
// CHECK-NEXT: [[vsharded_4:%.*]] = shard.shard [[vsharded]] to [[vsharding_3]] annotate_for_users : tensor<1024x1024xf32>
// CHECK-NEXT: [[vsharding_5:%.*]] = shard.sharding @grid4x4 split_axes = {{\[\[}}0]] : !shard.sharding
// CHECK-NEXT: [[vsharded_6:%.*]] = shard.shard [[vsharded_2]] to [[vsharding_5]] annotate_for_users : tensor<1024x1024xf32>
-// CHECK-NEXT: [[v1:%.*]] = linalg.add ins([[vsharded_4]], [[vcst_0]] : tensor<1024x1024xf32>, f32) outs([[vsharded_6]] : tensor<1024x1024xf32>) -> tensor<1024x1024xf32>
+// CHECK-NEXT: [[v1:%.*]] = linalg.elementwise kind=#linalg.elementwise_kind<add> indexing_maps = {{.*}} ins([[vsharded_4]], [[vcst_0]] : tensor<1024x1024xf32>, f32) outs([[vsharded_6]] : tensor<1024x1024xf32>) -> tensor<1024x1024xf32>
// CHECK-NEXT: [[vsharding_7:%.*]] = shard.sharding @grid4x4 split_axes = {{\[\[}}0]] : !shard.sharding
// CHECK-NEXT: [[vsharded_8:%.*]] = shard.shard [[v1]] to [[vsharding_7]] : tensor<1024x1024xf32>
func.func @test_shard_constant_back() -> (tensor<1024x1024xf32>) attributes {llvm.emit_c_interface} {
%cst_1 = arith.constant dense<0.000000e+00> : tensor<1024x1024xf32>
%ci = arith.constant 43.4e+00 : f32
%o1 = tensor.empty() : tensor<1024x1024xf32>
- %res = linalg.add ins(%cst_1, %ci : tensor<1024x1024xf32>, f32) outs(%o1 : tensor<1024x1024xf32>) -> tensor<1024x1024xf32>
+ %res = linalg.elementwise kind=#linalg.elementwise_kind<add> indexing_maps = [#id, #sc, #id] ins(%cst_1, %ci : tensor<1024x1024xf32>, f32) outs(%o1 : tensor<1024x1024xf32>) -> tensor<1024x1024xf32>
%sharding_1 = shard.sharding @grid4x4 split_axes = [[0]] : !shard.sharding
%sharded_1 = shard.shard %res to %sharding_1 : tensor<1024x1024xf32>
return %sharded_1 : tensor<1024x1024xf32>
diff --git a/mlir/test/Dialect/Linalg/block-pack-matmul.mlir b/mlir/test/Dialect/Linalg/block-pack-matmul.mlir
index e16af1f6da0e3..1017bc047c67b 100644
--- a/mlir/test/Dialect/Linalg/block-pack-matmul.mlir
+++ b/mlir/test/Dialect/Linalg/block-pack-matmul.mlir
@@ -142,7 +142,7 @@ func.func @block_matmul_with_consumer(
%0 = tensor.empty() : tensor<128x128xf32>
%1 = linalg.matmul ins(%A, %B : tensor<128x128xf32>, tensor<128x128xf32>)
outs(%C : tensor<128x128xf32>) -> tensor<128x128xf32>
- %2 = linalg.add ins(%1, %D : tensor<128x128xf32>, tensor<128x128xf32>)
+ %2 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%1, %D : tensor<128x128xf32>, tensor<128x128xf32>)
outs(%0 : tensor<128x128xf32>) -> tensor<128x128xf32>
return %2 : tensor<128x128xf32>
}
@@ -155,7 +155,7 @@ func.func @block_matmul_with_consumer(
// CHECK: %[[RES_UNPACKED:.+]] = linalg.unpack %[[GEMM_RES_PACKED]]
// CHECK-SAME: inner_dims_pos = [0, 1] inner_tiles = [32, 16]
// CHECK-SAME: into %[[C]] : tensor<4x8x32x16xf32> -> tensor<128x128xf32>
-// CHECK: %[[ADD_RES:.+]] = linalg.add
+// CHECK: %[[ADD_RES:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK-SAME: ins(%[[RES_UNPACKED]], %[[D]] : tensor<128x128xf32>, tensor<128x128xf32>) outs(%[[RES_DST]] : tensor<128x128xf32>)
// CHECK: return %[[ADD_RES]] : tensor<128x128xf32>
diff --git a/mlir/test/Dialect/Linalg/decompose-generic-by-unfolding-projected-permutation.mlir b/mlir/test/Dialect/Linalg/decompose-generic-by-unfolding-projected-permutation.mlir
index 38e406a13ec08..f9c986986eb33 100644
--- a/mlir/test/Dialect/Linalg/decompose-generic-by-unfolding-projected-permutation.mlir
+++ b/mlir/test/Dialect/Linalg/decompose-generic-by-unfolding-projected-permutation.mlir
@@ -20,7 +20,7 @@ func.func @transpose_and_broadcast(%x : tensor<7x8x9xf32>, %y: tensor<5x9x7x8x1
// CHECK: %[[X_trans:.+]] = linalg.transpose ins(%[[X]] : tensor<7x8x9xf32>) outs(%[[E0]] : tensor<9x7x8xf32>) permutation = [2, 0, 1]
// CHECK: %[[E1:.+]] = tensor.empty() : tensor<5x9x7x8x10xf32>
// CHECK: %[[X_trans_bc:.+]] = linalg.broadcast ins(%[[X_trans]] : tensor<9x7x8xf32>) outs(%[[E1]] : tensor<5x9x7x8x10xf32>) dimensions = [0, 4]
-// CHECK: {{.*}} = linalg.div ins(%[[X_trans_bc]], %[[Y]] : tensor<5x9x7x8x10xf32>, tensor<5x9x7x8x10xf32>) outs(%[[Z]] : tensor<5x9x7x8x10xf32>) -> tensor<5x9x7x8x10xf32>
+// CHECK: {{.*}} = linalg.elementwise kind=#linalg.elementwise_kind<div> ins(%[[X_trans_bc]], %[[Y]] : tensor<5x9x7x8x10xf32>, tensor<5x9x7x8x10xf32>) outs(%[[Z]] : tensor<5x9x7x8x10xf32>) -> tensor<5x9x7x8x10xf32>
// CHECK-NOT: linalg.generic
// -----
@@ -44,7 +44,7 @@ func.func @transpose_only(%x : tensor<32x2x16xf32>, %y: tensor<2x16x32xf32>, %z
// CHECK-SAME: %[[X:.+]]: tensor<32x2x16xf32>, %[[Y:.+]]: tensor<2x16x32xf32>, %[[Z:.+]]: tensor<2x16x32xf32>) -> tensor<2x16x32xf32> {
// CHECK: %[[E0:.+]] = tensor.empty() : tensor<2x16x32xf32>
// CHECK: %[[X_trans:.+]] = linalg.transpose ins(%[[X]] : tensor<32x2x16xf32>) outs(%[[E0]] : tensor<2x16x32xf32>) permutation = [1, 2, 0]
-// CHECK: {{.*}} = linalg.div ins(%[[X_trans]], %[[Y]] : tensor<2x16x32xf32>, tensor<2x16x32xf32>) outs(%[[Z]] : tensor<2x16x32xf32>) -> tensor<2x16x32xf32>
+// CHECK: {{.*}} = linalg.elementwise kind=#linalg.elementwise_kind<div> ins(%[[X_trans]], %[[Y]] : tensor<2x16x32xf32>, tensor<2x16x32xf32>) outs(%[[Z]] : tensor<2x16x32xf32>) -> tensor<2x16x32xf32>
// CHECK-NOT: linalg.generic
// -----
@@ -67,5 +67,5 @@ func.func @broadcast_only(%x : tensor<2x16x32xf32>, %y: tensor<2x32xf32>, %z :
// CHECK-SAME: %[[X:.+]]: tensor<2x16x32xf32>, %[[Y:.+]]: tensor<2x32xf32>, %[[Z:.+]]: tensor<2x16x32xf32>) -> tensor<2x16x32xf32> {
// CHECK: %[[E0:.+]] = tensor.empty() : tensor<2x16x32xf32>
// CHECK: %[[X_bc:.+]] = linalg.broadcast ins(%[[Y]] : tensor<2x32xf32>) outs(%[[E0]] : tensor<2x16x32xf32>) dimensions = [1]
-// CHECK: {{.*}} = linalg.div ins(%[[X]], %[[X_bc]] : tensor<2x16x32xf32>, tensor<2x16x32xf32>) outs(%arg2 : tensor<2x16x32xf32>) -> tensor<2x16x32xf32>
+// CHECK: {{.*}} = linalg.elementwise kind=#linalg.elementwise_kind<div> ins(%[[X]], %[[X_bc]] : tensor<2x16x32xf32>, tensor<2x16x32xf32>) outs(%arg2 : tensor<2x16x32xf32>) -> tensor<2x16x32xf32>
// CHECK-NOT: linalg.generic
diff --git a/mlir/test/Dialect/Linalg/elementwise/named-to-elementwise.mlir b/mlir/test/Dialect/Linalg/elementwise/named-to-elementwise.mlir
index 17276d30efcc8..3da231e729024 100644
--- a/mlir/test/Dialect/Linalg/elementwise/named-to-elementwise.mlir
+++ b/mlir/test/Dialect/Linalg/elementwise/named-to-elementwise.mlir
@@ -1,31 +1,5 @@
// RUN: mlir-opt %s -linalg-morph-ops=named-to-category -split-input-file | FileCheck %s
-// CHECK: @add(%[[A:.+]]: tensor<16x8xf32>, %[[B:.+]]: tensor<16x8xf32>, %[[C:.+]]: tensor<16x8xf32>) -> tensor<16x8xf32> {
-// CHECK: {{.*}} = linalg.elementwise
-// CHECK-SAME: kind=#linalg.elementwise_kind<add>
-// CHECK-SAME: ins(%[[A]], %[[B]] : tensor<16x8xf32>, tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[C]] : tensor<16x8xf32>) -> tensor<16x8xf32>
-//
-func.func @add(%A : tensor<16x8xf32>, %B: tensor<16x8xf32>, %C : tensor<16x8xf32>) -> tensor<16x8xf32> {
- %add = linalg.add ins(%A, %B : tensor<16x8xf32>, tensor<16x8xf32>) outs(%C : tensor<16x8xf32>) -> tensor<16x8xf32>
- return %add : tensor<16x8xf32>
-}
-
-// ----
-
-// CHECK: @sub(%[[A:.+]]: tensor<16x8xf32>, %[[B:.+]]: tensor<16x8xf32>, %[[C:.+]]: tensor<16x8xf32>) -> tensor<16x8xf32> {
-// CHECK: {{.*}} = linalg.elementwise
-// CHECK-SAME: kind=#linalg.elementwise_kind<sub>
-// CHECK-SAME: ins(%[[A]], %[[B]] : tensor<16x8xf32>, tensor<16x8xf32>)
-// CHECK-SAME: outs(%[[C]] : tensor<16x8xf32>)
-//
-func.func @sub(%A : tensor<16x8xf32>, %B: tensor<16x8xf32>, %C : tensor<16x8xf32>) -> tensor<16x8xf32> {
- %sub = linalg.sub ins(%A, %B : tensor<16x8xf32>, tensor<16x8xf32>) outs(%C : tensor<16x8xf32>) -> tensor<16x8xf32>
- return %sub : tensor<16x8xf32>
-}
-
-// ----
-
// CHECK: @ternary_select(%[[A:.+]]: tensor<4x8x16xi1>, %[[B:.+]]: tensor<4x8x16xf32>, %[[C:.+]]: tensor<4x8x16xf32>)
// CHECK: %[[E:.+]] = tensor.empty() : tensor<4x8x16xf32>
// CHECK: {{.*}} = linalg.elementwise
diff --git a/mlir/test/Dialect/Linalg/fold-add-into-dest.mlir b/mlir/test/Dialect/Linalg/fold-add-into-dest.mlir
index b29eb92ed83b4..815cbae4258bf 100644
--- a/mlir/test/Dialect/Linalg/fold-add-into-dest.mlir
+++ b/mlir/test/Dialect/Linalg/fold-add-into-dest.mlir
@@ -10,7 +10,7 @@ func.func @fold_add_on_two_matmuls(%arg0: !type, %arg1: !type) -> !type {
%4 = tensor.empty() : !type
%5 = linalg.fill ins(%cst : f32) outs(%1 : !type) -> !type
%6 = linalg.matmul ins(%arg1, %0 : !type, !type) outs(%5 : !type) -> !type
- %7 = linalg.add ins(%3, %6 : !type, !type) outs(%1 : !type) -> !type
+ %7 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%3, %6 : !type, !type) outs(%1 : !type) -> !type
return %7 : !type
}
@@ -22,7 +22,7 @@ func.func @fold_add_on_two_matmuls(%arg0: !type, %arg1: !type) -> !type {
// CHECK-NEXT: %[[FILLED:.*]] = linalg.fill ins(%[[ZERO]] : {{.*}}) outs(%[[EMPTY]] : {{.*}})
// CHECK-NEXT: %[[ACC:.+]] = linalg.matmul ins(%[[ARG0]], %[[DENSE]] : {{.*}}) outs(%[[FILLED]] : {{.*}})
// CHECK-NEXT: %[[RES:.+]] = linalg.matmul ins(%[[ARG1]], %[[DENSE]] : {{.*}}) outs(%[[ACC]] : {{.*}})
-// CHECK-NOT: linalg.add
+// CHECK-NOT: linalg.elementwise
// CHECK-NEXT: return %[[RES]]
module attributes {transform.with_named_sequence} {
@@ -44,7 +44,7 @@ func.func @expect_no_fold_of_add_as_orig_dest_not_additive_zero(%arg0: !type, %a
%2 = linalg.fill ins(%cst : f32) outs(%1 : !type) -> !type
%3 = linalg.matmul ins(%arg0, %0 : !type, !type) outs(%2 : !type) -> !type
%4 = linalg.matmul ins(%arg1, %0 : !type, !type) outs(%0 : !type) -> !type
- %5 = linalg.add ins(%3, %4 : !type, !type) outs(%1 : !type) -> !type
+ %5 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%3, %4 : !type, !type) outs(%1 : !type) -> !type
return %5 : !type
}
@@ -52,7 +52,7 @@ func.func @expect_no_fold_of_add_as_orig_dest_not_additive_zero(%arg0: !type, %a
// CHECK: linalg.fill
// CHECK-NEXT: linalg.matmul
// CHECK-NEXT: linalg.matmul
-// CHECK-NEXT: linalg.add
+// CHECK-NEXT: linalg.elementwise
// CHECK-NEXT: return
module attributes {transform.with_named_sequence} {
@@ -75,8 +75,8 @@ func.func @expect_no_fold_of_add_as_contraction_result_has_multiple_users(%arg0:
%2 = linalg.fill ins(%cst : f32) outs(%1 : !type) -> !type
%3 = linalg.matmul ins(%arg0, %0 : !type, !type) outs(%2 : !type) -> !type
%4 = linalg.matmul ins(%arg1, %0 : !type, !type) outs(%0 : !type) -> !type
- %5 = linalg.add ins(%3, %4 : !type, !type) outs(%1 : !type) -> !type
- %6 = linalg.mul ins(%4, %arg0 : !type, !type) outs(%1 : !type) -> !type
+ %5 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%3, %4 : !type, !type) outs(%1 : !type) -> !type
+ %6 = linalg.elementwise kind=#linalg.elementwise_kind<mul> ins(%4, %arg0 : !type, !type) outs(%1 : !type) -> !type
return %5, %6 : !type, !type
}
@@ -84,8 +84,8 @@ func.func @expect_no_fold_of_add_as_contraction_result_has_multiple_users(%arg0:
// CHECK: linalg.fill
// CHECK-NEXT: linalg.matmul
// CHECK-NEXT: linalg.matmul
-// CHECK-NEXT: linalg.add
-// CHECK-NEXT: linalg.mul
+// CHECK-NEXT: linalg.elementwise kind=#linalg.elementwise_kind<add>
+// CHECK-NEXT: linalg.elementwise kind=#linalg.elementwise_kind<mul>
// CHECK-NEXT: return
module attributes {transform.with_named_sequence} {
@@ -107,13 +107,13 @@ func.func @fold_add_on_matmul_and_func_arg(%arg0: !type, %arg1: !type) -> !type
%1 = tensor.empty() : !type
%2 = linalg.fill ins(%cst : f32) outs(%1 : !type) -> !type
%3 = linalg.matmul ins(%arg0, %0 : !type, !type) outs(%2 : !type) -> !type
- %5 = linalg.add ins(%3, %arg1 : !type, !type) outs(%1 : !type) -> !type
+ %5 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%3, %arg1 : !type, !type) outs(%1 : !type) -> !type
return %5 : !type
}
// CHECK-LABEL: func.func @fold_add_on_matmul_and_func_arg
// CHECK: %[[RES:.+]] = linalg.matmul
-// CHECK-NOT: linalg.add
+// CHECK-NOT: linalg.elementwise
// CHECK-NEXT: return %[[RES]]
module attributes {transform.with_named_sequence} {
@@ -135,14 +135,14 @@ func.func @expect_no_fold_of_add_as_operands_do_not_dominate_each_other(%arg0: !
%1 = tensor.empty() : !type
%2 = linalg.fill ins(%cst : f32) outs(%1 : !type) -> !type
%3 = linalg.matmul ins(%arg0, %0 : !type, !type) outs(%2 : !type) -> !type
- %4 = linalg.add ins(%3, %3 : !type, !type) outs(%1 : !type) -> !type
+ %4 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%3, %3 : !type, !type) outs(%1 : !type) -> !type
return %4 : !type
}
// CHECK-LABEL: func.func @expect_no_fold_of_add_as_operands_do_not_dominate_each_other
// CHECK: linalg.fill
// CHECK-NEXT: linalg.matmul
-// CHECK-NEXT: linalg.add
+// CHECK-NEXT: linalg.elementwise
// CHECK-NEXT: return
module attributes {transform.with_named_sequence} {
@@ -164,16 +164,16 @@ func.func @expect_no_fold_of_add_as_dominated_op_is_not_a_contraction(%arg0: !ty
%1 = tensor.empty() : !type
%2 = linalg.fill ins(%cst : f32) outs(%1 : !type) -> !type
%3 = linalg.matmul ins(%arg0, %0 : !type, !type) outs(%2 : !type) -> !type
- %4 = linalg.sub ins(%arg1, %0 : !type, !type) outs(%2 : !type) -> !type
- %5 = linalg.add ins(%3, %4 : !type, !type) outs(%1 : !type) -> !type
+ %4 = linalg.elementwise kind=#linalg.elementwise_kind<sub> ins(%arg1, %0 : !type, !type) outs(%2 : !type) -> !type
+ %5 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%3, %4 : !type, !type) outs(%1 : !type) -> !type
return %5 : !type
}
// CHECK-LABEL: func.func @expect_no_fold_of_add_as_dominated_op_is_not_a_contraction
// CHECK: linalg.fill
// CHECK-NEXT: linalg.matmul
-// CHECK-NEXT: linalg.sub
-// CHECK-NEXT: linalg.add
+// CHECK-NEXT: linalg.elementwise kind=#linalg.elementwise_kind<sub>
+// CHECK-NEXT: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK-NEXT: return
module attributes {transform.with_named_sequence} {
@@ -206,14 +206,14 @@ func.func @expect_no_fold_of_add_as_dest_accumulation_is_not_identity_mapped(%ar
%6 = arith.addf %c, %5 : f32
linalg.yield %6 : f32
} -> !type
- %4 = linalg.add ins(%3, %arg1 : !type, !type) outs(%1 : !type) -> !type
+ %4 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%3, %arg1 : !type, !type) outs(%1 : !type) -> !type
return %4 : !type
}
// CHECK-LABEL: func.func @expect_no_fold_of_add_as_dest_accumulation_is_not_identity_mapped
// CHECK: linalg.fill
// CHECK-NEXT: linalg.generic
-// CHECK: linalg.add
+// CHECK: linalg.elementwise
// CHECK-NEXT: return
module attributes {transform.with_named_sequence} {
@@ -246,13 +246,13 @@ func.func @fold_add_on_a_generic_and_an_argument(%arg0: !type, %arg1: !type) ->
%6 = arith.addf %c, %5 : f32
linalg.yield %6 : f32
} -> !type
- %4 = linalg.add ins(%3, %arg1 : !type, !type) outs(%1 : !type) -> !type
+ %4 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%3, %arg1 : !type, !type) outs(%1 : !type) -> !type
return %4 : !type
}
// CHECK-LABEL: func.func @fold_add_on_a_generic_and_an_argument
// CHECK: linalg.generic
-// CHECK-NOT: linalg.add
+// CHECK-NOT: linalg.elementwise
// CHECK: return
module attributes {transform.with_named_sequence} {
@@ -277,7 +277,7 @@ func.func @expect_no_fold_due_to_no_memref_support(%arg0: memref<2048x2048xf32>,
linalg.matmul ins(%arg0, %0 : memref<2048x2048xf32>, memref<2048x2048xf32>) outs(%alloc_0 : memref<2048x2048xf32>)
linalg.fill ins(%cst : f32) outs(%alloc : memref<2048x2048xf32>)
linalg.matmul ins(%arg1, %0 : memref<2048x2048xf32>, memref<2048x2048xf32>) outs(%alloc : memref<2048x2048xf32>)
- linalg.add ins(%alloc_0, %alloc : memref<2048x2048xf32>, memref<2048x2048xf32>) outs(%alloc : memref<2048x2048xf32>)
+ linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%alloc_0, %alloc : memref<2048x2048xf32>, memref<2048x2048xf32>) outs(%alloc : memref<2048x2048xf32>)
memref.dealloc %alloc_0 : memref<2048x2048xf32>
return %alloc : memref<2048x2048xf32>
}
@@ -285,7 +285,7 @@ func.func @expect_no_fold_due_to_no_memref_support(%arg0: memref<2048x2048xf32>,
// CHECK-LABEL: func.func @expect_no_fold_due_to_no_memref_support
// CHECK: linalg.matmul
// CHECK: linalg.matmul
-// CHECK: linalg.add
+// CHECK: linalg.elementwise
// CHECK: return
module attributes {transform.with_named_sequence} {
@@ -305,14 +305,14 @@ func.func @expect_no_fold_when_dominated_dest_is_block_arg(
%lhs: !type, %rhs: !type, %dest: !type, %other: !type) -> !type {
%0 = linalg.matmul ins(%lhs, %rhs : !type, !type) outs(%dest : !type) -> !type
%1 = tensor.empty() : !type
- %2 = linalg.add ins(%0, %other : !type, !type) outs(%1 : !type) -> !type
+ %2 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %other : !type, !type) outs(%1 : !type) -> !type
return %2 : !type
}
// CHECK-LABEL: func.func @expect_no_fold_when_dominated_dest_is_block_arg
// CHECK: linalg.matmul
// CHECK-NEXT: tensor.empty
-// CHECK-NEXT: linalg.add
+// CHECK-NEXT: linalg.elementwise
// CHECK-NEXT: return
module attributes {transform.with_named_sequence} {
diff --git a/mlir/test/Dialect/Linalg/generalize-named-ops.mlir b/mlir/test/Dialect/Linalg/generalize-named-ops.mlir
index 41e0123c3a78b..34460d7421d1e 100644
--- a/mlir/test/Dialect/Linalg/generalize-named-ops.mlir
+++ b/mlir/test/Dialect/Linalg/generalize-named-ops.mlir
@@ -404,208 +404,6 @@ func.func @generalize_linalg_map(%arg0: memref<1x8x8x8xf32>, %arg1: memref<1x8x8
// CHECK: %[[ADD:.+]] = arith.addf %[[BBARG0]], %[[BBARG1]] : f32
// CHECK: linalg.yield %[[ADD]] : f32
-// -----
-
-func.func @generalize_add(%lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>,
- %out: memref<7x14x21xf32>) {
- linalg.add ins(%lhs, %rhs : memref<7x14x21xf32>, memref<7x14x21xf32>)
- outs(%out : memref<7x14x21xf32>)
- return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_add
-// CHECK-SAME: (%[[LHS:.+]]: memref<7x14x21xf32>, %[[RHS:.+]]: memref<7x14x21xf32>,
-// CHECK-SAME: %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME: ins(%[[LHS]], %[[RHS]] : memref<7x14x21xf32>, memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK: ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32, %[[BBARG2:.+]]: f32)
-// CHECK-NEXT: %[[SUM:.+]] = arith.addf %[[BBARG0]], %[[BBARG1]] : f32
-// CHECK-NEXT: linalg.yield %[[SUM]] : f32
-
-// -----
-
-func.func @generalize_sub(%lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>,
- %out: memref<7x14x21xf32>) {
- linalg.sub ins(%lhs, %rhs : memref<7x14x21xf32>, memref<7x14x21xf32>)
- outs(%out : memref<7x14x21xf32>)
- return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_sub
-// CHECK-SAME: (%[[LHS:.+]]: memref<7x14x21xf32>, %[[RHS:.+]]: memref<7x14x21xf32>,
-// CHECK-SAME: %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME: ins(%[[LHS]], %[[RHS]] : memref<7x14x21xf32>, memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK: ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32, %[[BBARG2:.+]]: f32)
-// CHECK-NEXT: %[[SUB:.+]] = arith.subf %[[BBARG0]], %[[BBARG1]] : f32
-// CHECK-NEXT: linalg.yield %[[SUB]] : f32
-
-// -----
-
-func.func @generalize_mul(%lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>,
- %out: memref<7x14x21xf32>) {
- linalg.mul ins(%lhs, %rhs : memref<7x14x21xf32>, memref<7x14x21xf32>)
- outs(%out : memref<7x14x21xf32>)
- return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_mul
-// CHECK-SAME: (%[[LHS:.+]]: memref<7x14x21xf32>, %[[RHS:.+]]: memref<7x14x21xf32>,
-// CHECK-SAME: %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME: ins(%[[LHS]], %[[RHS]] : memref<7x14x21xf32>, memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK: ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32, %[[BBARG2:.+]]: f32)
-// CHECK-NEXT: %[[MUL:.+]] = arith.mulf %[[BBARG0]], %[[BBARG1]] : f32
-// CHECK-NEXT: linalg.yield %[[MUL]] : f32
-
-// -----
-
-func.func @generalize_div(%lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>,
- %out: memref<7x14x21xf32>) {
- linalg.div ins(%lhs, %rhs : memref<7x14x21xf32>, memref<7x14x21xf32>)
- outs(%out : memref<7x14x21xf32>)
- return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_div
-// CHECK-SAME: (%[[LHS:.+]]: memref<7x14x21xf32>, %[[RHS:.+]]: memref<7x14x21xf32>,
-// CHECK-SAME: %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME: ins(%[[LHS]], %[[RHS]] : memref<7x14x21xf32>, memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK: ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32, %[[BBARG2:.+]]: f32)
-// CHECK-NEXT: %[[DIV:.+]] = arith.divf %[[BBARG0]], %[[BBARG1]] : f32
-// CHECK-NEXT: linalg.yield %[[DIV]] : f32
-
-// -----
-
-func.func @generalize_divu(%lhs: memref<7x14x21xi32>, %rhs: memref<7x14x21xi32>,
- %out: memref<7x14x21xi32>) {
- linalg.div_unsigned ins(%lhs, %rhs : memref<7x14x21xi32>, memref<7x14x21xi32>)
- outs(%out : memref<7x14x21xi32>)
- return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_divu
-// CHECK-SAME: (%[[LHS:.+]]: memref<7x14x21xi32>, %[[RHS:.+]]: memref<7x14x21xi32>,
-// CHECK-SAME: %[[OUT:.+]]: memref<7x14x21xi32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME: ins(%[[LHS]], %[[RHS]] : memref<7x14x21xi32>, memref<7x14x21xi32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xi32>)
-
-// CHECK: ^{{.+}}(%[[BBARG0:.+]]: i32, %[[BBARG1:.+]]: i32, %[[BBARG2:.+]]: i32)
-// CHECK-NEXT: %[[DIVU:.+]] = arith.divui %[[BBARG0]], %[[BBARG1]] : i32
-// CHECK-NEXT: linalg.yield %[[DIVU]] : i32
-
-// -----
-
-func.func @generalize_max(%lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>,
- %out: memref<7x14x21xf32>) {
- linalg.max ins(%lhs, %rhs : memref<7x14x21xf32>, memref<7x14x21xf32>)
- outs(%out : memref<7x14x21xf32>)
- return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_max
-// CHECK-SAME: (%[[LHS:.+]]: memref<7x14x21xf32>, %[[RHS:.+]]: memref<7x14x21xf32>,
-// CHECK-SAME: %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME: ins(%[[LHS]], %[[RHS]] : memref<7x14x21xf32>, memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK: ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32, %[[BBARG2:.+]]: f32)
-// CHECK-NEXT: %[[max:.+]] = arith.maximumf %[[BBARG0]], %[[BBARG1]] : f32
-// CHECK-NEXT: linalg.yield %[[max]] : f32
-
-// -----
-
-func.func @generalize_min(%lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>,
- %out: memref<7x14x21xf32>) {
- linalg.min ins(%lhs, %rhs : memref<7x14x21xf32>, memref<7x14x21xf32>)
- outs(%out : memref<7x14x21xf32>)
- return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_min
-// CHECK-SAME: (%[[LHS:.+]]: memref<7x14x21xf32>, %[[RHS:.+]]: memref<7x14x21xf32>,
-// CHECK-SAME: %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME: ins(%[[LHS]], %[[RHS]] : memref<7x14x21xf32>, memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK: ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32, %[[BBARG2:.+]]: f32)
-// CHECK-NEXT: %[[min:.+]] = arith.minimumf %[[BBARG0]], %[[BBARG1]] : f32
-// CHECK-NEXT: linalg.yield %[[min]] : f32
-
-
-// -----
-
-func.func @generalize_powf(%lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>,
- %out: memref<7x14x21xf32>) {
- linalg.powf ins(%lhs, %rhs : memref<7x14x21xf32>, memref<7x14x21xf32>)
- outs(%out : memref<7x14x21xf32>)
- return
-}
-
-// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-
-// CHECK: func @generalize_powf
-// CHECK-SAME: (%[[LHS:.+]]: memref<7x14x21xf32>, %[[RHS:.+]]: memref<7x14x21xf32>,
-// CHECK-SAME: %[[OUT:.+]]: memref<7x14x21xf32>)
-
-// CHECK: linalg.generic
-// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]]]
-// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]}
-// CHECK-SAME: ins(%[[LHS]], %[[RHS]] : memref<7x14x21xf32>, memref<7x14x21xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>)
-
-// CHECK: ^{{.+}}(%[[BBARG0:.+]]: f32, %[[BBARG1:.+]]: f32, %[[BBARG2:.+]]: f32)
-// CHECK-NEXT: %[[powf:.+]] = math.powf %[[BBARG0]], %[[BBARG1]] : f32
-// CHECK-NEXT: linalg.yield %[[powf]] : f32
-
-
// -----
func.func @generalize_select(%cond: memref<7x14x21xi1>, %lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>,
diff --git a/mlir/test/Dialect/Linalg/invalid.mlir b/mlir/test/Dialect/Linalg/invalid.mlir
index a5ec1fcc58880..67ed18c3dd4b1 100644
--- a/mlir/test/Dialect/Linalg/invalid.mlir
+++ b/mlir/test/Dialect/Linalg/invalid.mlir
@@ -2180,16 +2180,6 @@ func.func @pooling_nwc_min_unsigned_i1(
// correctly.
//===----------------------------------------------------------------------===//
-module {
- func.func @add_invalid_mixed_types(%in_f32: memref<3xf32>, %in_i32 : memref< 3xi32>, %out_f32: memref<3xf32>, %arg3: memref<3xf32>) {
- // expected-error @below {{Cannot build binary Linalg operation: expects allComplex, allFloatingPoint, or allInteger, got 'f32' and 'i32'}}
- linalg.add ins(%in_f32, %in_i32 : memref<3xf32>, memref< 3xi32>) outs(%out_f32 : memref<3xf32>)
- return
- }
-}
-
-// -----
-
func.func @matmul_invalid_mixed_types(%t: tensor<?xf16>, %f: vector<4xf16>)
-> (tensor<?xf16>, vector<4xf16>)
{
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 63550cf92e2c4..16206c7e837c8 100644
--- a/mlir/test/Dialect/Linalg/linalg-morph-elementwise-to-named.mlir
+++ b/mlir/test/Dialect/Linalg/linalg-morph-elementwise-to-named.mlir
@@ -35,26 +35,25 @@ func.func @binary_ops_int(%A: tensor<?x?xi32>, %B: tensor<?x?xi32>,
// CHECK-LABEL: binary_ops_int
// CHECK-SAME: %[[A:.+]]: tensor<?x?xi32>, %[[B:.+]]: tensor<?x?xi32>,
// CHECK-SAME: %[[OUT:.+]]: tensor<?x?xi32>)
-// CHECK-NOT: linalg.elementwise
-// CHECK: %[[ADD:.+]] = linalg.add
+// CHECK: %[[ADD:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK-SAME: ins(%[[A]], %[[B]] : tensor<?x?xi32>, tensor<?x?xi32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xi32>) -> tensor<?x?xi32>
-// CHECK: %[[SUB:.+]] = linalg.sub
+// CHECK: %[[SUB:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<sub>
// CHECK-SAME: ins(%[[ADD]], %[[B]] : tensor<?x?xi32>, tensor<?x?xi32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xi32>) -> tensor<?x?xi32>
-// CHECK: %[[MUL:.+]] = linalg.mul
+// CHECK: %[[MUL:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// CHECK-SAME: ins(%[[SUB]], %[[B]] : tensor<?x?xi32>, tensor<?x?xi32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xi32>) -> tensor<?x?xi32>
-// CHECK: %[[DIV:.+]] = linalg.div
+// CHECK: %[[DIV:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<div>
// CHECK-SAME: ins(%[[MUL]], %[[B]] : tensor<?x?xi32>, tensor<?x?xi32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xi32>) -> tensor<?x?xi32>
-// CHECK: %[[DIVU:.+]] = linalg.div_unsigned
+// CHECK: %[[DIVU:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<div_unsigned>
// CHECK-SAME: ins(%[[DIV]], %[[B]] : tensor<?x?xi32>, tensor<?x?xi32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xi32>) -> tensor<?x?xi32>
-// CHECK: %[[MAX:.+]] = linalg.max
+// CHECK: %[[MAX:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<max_signed>
// CHECK-SAME: ins(%[[DIVU]], %[[B]] : tensor<?x?xi32>, tensor<?x?xi32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xi32>) -> tensor<?x?xi32>
-// CHECK: linalg.min
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<min_signed>
// CHECK-SAME: ins(%[[MAX]], %[[B]] : tensor<?x?xi32>, tensor<?x?xi32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xi32>) -> tensor<?x?xi32>
@@ -89,26 +88,25 @@ func.func @binary_ops_float(%A: tensor<?x?xf32>, %B: tensor<?x?xf32>,
// CHECK-LABEL: binary_ops_float
// CHECK-SAME: %[[A:.+]]: tensor<?x?xf32>, %[[B:.+]]: tensor<?x?xf32>,
// CHECK-SAME: %[[OUT:.+]]: tensor<?x?xf32>)
-// CHECK-NOT: linalg.elementwise
-// CHECK: %[[ADD:.+]] = linalg.add
+// CHECK: %[[ADD:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK-SAME: ins(%[[A]], %[[B]] : tensor<?x?xf32>, tensor<?x?xf32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK: %[[SUB:.+]] = linalg.sub
+// CHECK: %[[SUB:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<sub>
// CHECK-SAME: ins(%[[ADD]], %[[B]] : tensor<?x?xf32>, tensor<?x?xf32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK: %[[MUL:.+]] = linalg.mul
+// CHECK: %[[MUL:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// CHECK-SAME: ins(%[[SUB]], %[[B]] : tensor<?x?xf32>, tensor<?x?xf32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK: %[[DIV:.+]] = linalg.div
+// CHECK: %[[DIV:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<div>
// CHECK-SAME: ins(%[[MUL]], %[[B]] : tensor<?x?xf32>, tensor<?x?xf32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK: %[[MAX:.+]] = linalg.max
+// CHECK: %[[MAX:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<max_signed>
// CHECK-SAME: ins(%[[DIV]], %[[B]] : tensor<?x?xf32>, tensor<?x?xf32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK: %[[MIN:.+]] = linalg.min
+// CHECK: %[[MIN:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<min_signed>
// CHECK-SAME: ins(%[[MAX]], %[[B]] : tensor<?x?xf32>, tensor<?x?xf32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK: linalg.powf
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<powf>
// CHECK-SAME: ins(%[[MIN]], %[[B]] : tensor<?x?xf32>, tensor<?x?xf32>)
// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
diff --git a/mlir/test/Dialect/Linalg/linalg-morph-multi-step.mlir b/mlir/test/Dialect/Linalg/linalg-morph-multi-step.mlir
deleted file mode 100644
index d7663c04bb213..0000000000000
--- a/mlir/test/Dialect/Linalg/linalg-morph-multi-step.mlir
+++ /dev/null
@@ -1,135 +0,0 @@
-// RUN: mlir-opt %s -linalg-morph-ops=named-to-generic -split-input-file | \
-// RUN: FileCheck %s --check-prefix=ALL,NAMED_TO_GENERIC
-// RUN: mlir-opt %s -linalg-morph-ops=named-to-generic -split-input-file | \
-// RUN: mlir-opt -linalg-morph-ops=generic-to-named -split-input-file | \
-// RUN: FileCheck %s --check-prefix=ALL,ROUND_TRIP
-
-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>)
- outs(%Out : tensor<?x?xi32>) -> tensor<?x?xi32>
- %1 = linalg.sub ins(%0, %B : tensor<?x?xi32>, tensor<?x?xi32>)
- outs(%Out : tensor<?x?xi32>) -> tensor<?x?xi32>
- %2 = linalg.mul ins(%1, %B : tensor<?x?xi32>, tensor<?x?xi32>)
- outs(%Out : tensor<?x?xi32>) -> tensor<?x?xi32>
- %3 = linalg.div ins(%2, %B : tensor<?x?xi32>, tensor<?x?xi32>)
- outs(%Out : tensor<?x?xi32>) -> tensor<?x?xi32>
- %4 = linalg.div_unsigned ins(%3, %B : tensor<?x?xi32>, tensor<?x?xi32>)
- outs(%Out : tensor<?x?xi32>) -> tensor<?x?xi32>
- %5 = linalg.max ins(%4, %B : tensor<?x?xi32>, tensor<?x?xi32>)
- outs(%Out : tensor<?x?xi32>) -> tensor<?x?xi32>
- %6 = linalg.min ins(%5, %B : tensor<?x?xi32>, tensor<?x?xi32>)
- outs(%Out : tensor<?x?xi32>) -> tensor<?x?xi32>
- return %6 : tensor<?x?xi32>
-}
-
-// ALL-LABEL: binary_ops_int
-
-// NAMED_TO_GENERIC-COUNT-7: linalg.generic
-// NAMED_TO_GENERIC-NOT: linalg.add
-// NAMED_TO_GENERIC-NOT: linalg.sub
-// NAMED_TO_GENERIC-NOT: linalg.mul
-// NAMED_TO_GENERIC-NOT: linalg.div
-// NAMED_TO_GENERIC-NOT: linalg.div_unsigned
-// NAMED_TO_GENERIC-NOT: linalg.max
-// NAMED_TO_GENERIC-NOT: linalg.min
-
-// ROUND_TRIP: linalg.add
-// ROUND_TRIP: linalg.sub
-// ROUND_TRIP: linalg.mul
-// ROUND_TRIP: linalg.div
-// ROUND_TRIP: linalg.div_unsigned
-// ROUND_TRIP: linalg.max
-// ROUND_TRIP: linalg.min
-// ROUND_TRIP-NOT: linalg.generic
-
-// -----
-
-func.func @binary_ops_float(%A: tensor<?x?xf32>, %B: tensor<?x?xf32>,
- %Out: tensor<?x?xf32>) -> tensor<?x?xf32> {
- %0 = linalg.add ins(%A, %B : tensor<?x?xf32>, tensor<?x?xf32>)
- outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
- %1 = linalg.sub ins(%0, %B : tensor<?x?xf32>, tensor<?x?xf32>)
- outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
- %2 = linalg.mul ins(%1, %B : tensor<?x?xf32>, tensor<?x?xf32>)
- outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
- %3 = linalg.div ins(%2, %B : tensor<?x?xf32>, tensor<?x?xf32>)
- outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
- %4 = linalg.max ins(%3, %B : tensor<?x?xf32>, tensor<?x?xf32>)
- outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
- %5 = linalg.min ins(%4, %B : tensor<?x?xf32>, tensor<?x?xf32>)
- outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
- %6 = linalg.powf ins(%5, %B : tensor<?x?xf32>, tensor<?x?xf32>)
- outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
- return %6 : tensor<?x?xf32>
-}
-
-// ALL-LABEL: binary_ops_float
-
-// NAMED_TO_GENERIC-COUNT-7: linalg.generic
-// NAMED_TO_GENERIC-NOT: linalg.add
-// NAMED_TO_GENERIC-NOT: linalg.sub
-// NAMED_TO_GENERIC-NOT: linalg.mul
-// NAMED_TO_GENERIC-NOT: linalg.div
-// NAMED_TO_GENERIC-NOT: linalg.max
-// NAMED_TO_GENERIC-NOT: linalg.min
-// NAMED_TO_GENERIC-NOT: linalg.powf
-
-// ROUND_TRIP: linalg.add
-// ROUND_TRIP: linalg.sub
-// ROUND_TRIP: linalg.mul
-// ROUND_TRIP: linalg.div
-// ROUND_TRIP: linalg.max
-// ROUND_TRIP: linalg.min
-// ROUND_TRIP: linalg.powf
-// ROUND_TRIP-NOT: linalg.generic
-
-// -----
-
-func.func @binary_ops_complex(%A: tensor<?x?xcomplex<f32>>, %B: tensor<?x?xcomplex<f32>>,
- %Out: tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>> {
- %0 = linalg.add ins(%A, %B : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>)
- outs(%Out : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
- %1 = linalg.sub ins(%0, %B : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>)
- outs(%Out : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
- %2 = linalg.mul ins(%1, %B : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>)
- outs(%Out : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
- %3 = linalg.div ins(%2, %B : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>)
- outs(%Out : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
- return %3 : tensor<?x?xcomplex<f32>>
-}
-
-// ALL-LABEL: binary_ops_complex
-
-// NAMED_TO_GENERIC-COUNT-4: linalg.generic
-// NAMED_TO_GENERIC-NOT: linalg.add
-// NAMED_TO_GENERIC-NOT: linalg.sub
-// NAMED_TO_GENERIC-NOT: linalg.mul
-// NAMED_TO_GENERIC-NOT: linalg.div
-
-// ROUND_TRIP: linalg.add
-// ROUND_TRIP: linalg.sub
-// ROUND_TRIP: linalg.mul
-// ROUND_TRIP: linalg.div
-// ROUND_TRIP-NOT: linalg.generic
-
-// -----
-
-func.func @binary_ops_bool(%A: tensor<?x?xi1>, %B: tensor<?x?xi1>,
- %Out: tensor<?x?xi1>) -> tensor<?x?xi1> {
- %0 = linalg.add ins(%A, %B : tensor<?x?xi1>, tensor<?x?xi1>)
- outs(%Out : tensor<?x?xi1>) -> tensor<?x?xi1>
- %1 = linalg.mul ins(%0, %B : tensor<?x?xi1>, tensor<?x?xi1>)
- outs(%Out : tensor<?x?xi1>) -> tensor<?x?xi1>
- return %1 : tensor<?x?xi1>
-}
-
-// ALL-LABEL: binary_ops_bool
-
-// NAMED_TO_GENERIC-COUNT-2: linalg.generic
-// NAMED_TO_GENERIC-NOT: linalg.add
-// NAMED_TO_GENERIC-NOT: linalg.mul
-
-// ROUND_TRIP: linalg.add
-// ROUND_TRIP: linalg.mul
-// ROUND_TRIP-NOT: linalg.generic
diff --git a/mlir/test/Dialect/Linalg/named-ops-fail.mlir b/mlir/test/Dialect/Linalg/named-ops-fail.mlir
index cd7e3498b9b0e..b1809e652aabe 100644
--- a/mlir/test/Dialect/Linalg/named-ops-fail.mlir
+++ b/mlir/test/Dialect/Linalg/named-ops-fail.mlir
@@ -1,133 +1,5 @@
// RUN: not mlir-opt -split-input-file -verify-diagnostics %s 2>&1 | FileCheck %s
-func.func @add_type_cast(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf16>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op requires the same type for all operands and results
- linalg.add ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf16>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @add_broadcast(%arg0: memref<8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
- linalg.add ins(%arg0, %arg1 : memref<8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @sub_type_cast(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf16>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op requires the same type for all operands and results
- linalg.sub ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf16>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @sub_broadcast(%arg0: memref<8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
- linalg.sub ins(%arg0, %arg1 : memref<8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @mul_type_cast(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf16>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op requires the same type for all operands and results
- linalg.mul ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf16>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @mul_broadcast(%arg0: memref<8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
- linalg.mul ins(%arg0, %arg1 : memref<8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @div_type_cast(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf16>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op requires the same type for all operands and results
- linalg.div ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf16>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @div_broadcast(%arg0: memref<8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
- linalg.div ins(%arg0, %arg1 : memref<8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @divu_type_cast(%arg0: memref<4x8x16xi32>, %arg1: memref<4x8x16xi16>, %arg2: memref<4x8x16xi32>) {
- // CHECK: op requires the same type for all operands and results
- linalg.div_unsigned ins(%arg0, %arg1 : memref<4x8x16xi32>, memref<4x8x16xi16>) outs(%arg2: memref<4x8x16xi32>)
- return
-}
-
-// -----
-
-func.func @divu_broadcast(%arg0: memref<8x16xi32>, %arg1: memref<4x8x16xi32>, %arg2: memref<4x8x16xi32>) {
- // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
- linalg.div_unsigned ins(%arg0, %arg1 : memref<8x16xi32>, memref<4x8x16xi32>) outs(%arg2: memref<4x8x16xi32>)
- 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>)
- return
-}
-
-// -----
-
-func.func @max_broadcast(%arg0: memref<8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
- linalg.max ins(%arg0, %arg1 : memref<8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @min_type_cast(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf16>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op requires the same type for all operands and results
- linalg.min ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf16>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @min_broadcast(%arg0: memref<8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
- linalg.min ins(%arg0, %arg1 : memref<8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @powf_type_cast(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf16>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op requires the same type for all operands and results
- linalg.powf ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf16>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-func.func @powf_broadcast(%arg0: memref<8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: op expected operand #0 rank (2) to match the result rank of indexing_map (3)
- linalg.powf ins(%arg0, %arg1 : memref<8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
func.func @select_type_cast(%arg0: memref<4x8x16xi1>, %arg1: memref<4x8x16xf16>, %arg2: memref<4x8x16xf32>, %arg3: memref<4x8x16xf32>) {
// CHECK: op failed to verify that all of {true_value, false_value, result} have same type
linalg.select ins(%arg0, %arg1, %arg2 : memref<4x8x16xi1>, memref<4x8x16xf16>, memref<4x8x16xf32>) outs(%arg3: memref<4x8x16xf32>)
diff --git a/mlir/test/Dialect/Linalg/named-ops.mlir b/mlir/test/Dialect/Linalg/named-ops.mlir
index e1efbf7ab18c6..f0003f93bc2e0 100644
--- a/mlir/test/Dialect/Linalg/named-ops.mlir
+++ b/mlir/test/Dialect/Linalg/named-ops.mlir
@@ -2000,278 +2000,6 @@ func.func @batch_mmt4d(%arg0: tensor<128x10x32x8x1xf32>, %arg1: tensor<128x80x32
// -----
-// CHECK-LABEL: func @add_dynamic
-func.func @add_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>, %arg2: memref<?x?x?xf32>) {
- // CHECK: linalg.add
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<?x?x?xf32>, memref<?x?x?xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<?x?x?xf32>)
- linalg.add ins(%arg0, %arg1 : memref<?x?x?xf32>, memref<?x?x?xf32>) outs(%arg2: memref<?x?x?xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @add_static
-func.func @add_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: linalg.add
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<4x8x16xf32>, memref<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<4x8x16xf32>)
- linalg.add ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @add_tensor
-func.func @add_tensor(%arg0: tensor<4x8x16xf32>, %arg1: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
- %0 = tensor.empty() : tensor<4x8x16xf32>
- // CHECK: linalg.add
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : tensor<4x8x16xf32>, tensor<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : tensor<4x8x16xf32>)
- %1 = linalg.add ins(%arg0, %arg1 : tensor<4x8x16xf32>, tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
- return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @sub_dynamic
-func.func @sub_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>, %arg2: memref<?x?x?xf32>) {
- // CHECK: linalg.sub
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<?x?x?xf32>, memref<?x?x?xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<?x?x?xf32>)
- linalg.sub ins(%arg0, %arg1 : memref<?x?x?xf32>, memref<?x?x?xf32>) outs(%arg2: memref<?x?x?xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @sub_static
-func.func @sub_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: linalg.sub
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<4x8x16xf32>, memref<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<4x8x16xf32>)
- linalg.sub ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @sub_tensor
-func.func @sub_tensor(%arg0: tensor<4x8x16xf32>, %arg1: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
- %0 = tensor.empty() : tensor<4x8x16xf32>
- // CHECK: linalg.sub
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : tensor<4x8x16xf32>, tensor<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : tensor<4x8x16xf32>)
- %1 = linalg.sub ins(%arg0, %arg1 : tensor<4x8x16xf32>, tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
- return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @mul_dynamic
-func.func @mul_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>, %arg2: memref<?x?x?xf32>) {
- // CHECK: linalg.mul
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<?x?x?xf32>, memref<?x?x?xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<?x?x?xf32>)
- linalg.mul ins(%arg0, %arg1 : memref<?x?x?xf32>, memref<?x?x?xf32>) outs(%arg2: memref<?x?x?xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @mul_static
-func.func @mul_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: linalg.mul
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<4x8x16xf32>, memref<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<4x8x16xf32>)
- linalg.mul ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @mul_tensor
-func.func @mul_tensor(%arg0: tensor<4x8x16xf32>, %arg1: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
- %0 = tensor.empty() : tensor<4x8x16xf32>
- // CHECK: linalg.mul
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : tensor<4x8x16xf32>, tensor<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : tensor<4x8x16xf32>)
- %1 = linalg.mul ins(%arg0, %arg1 : tensor<4x8x16xf32>, tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
- return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @div_dynamic
-func.func @div_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>, %arg2: memref<?x?x?xf32>) {
- // CHECK: linalg.div
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<?x?x?xf32>, memref<?x?x?xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<?x?x?xf32>)
- linalg.div ins(%arg0, %arg1 : memref<?x?x?xf32>, memref<?x?x?xf32>) outs(%arg2: memref<?x?x?xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @div_static
-func.func @div_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: linalg.div
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<4x8x16xf32>, memref<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<4x8x16xf32>)
- linalg.div ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @div_tensor
-func.func @div_tensor(%arg0: tensor<4x8x16xf32>, %arg1: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
- %0 = tensor.empty() : tensor<4x8x16xf32>
- // CHECK: linalg.div
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : tensor<4x8x16xf32>, tensor<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : tensor<4x8x16xf32>)
- %1 = linalg.div ins(%arg0, %arg1 : tensor<4x8x16xf32>, tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
- return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @div_unsigned_dynamic
-func.func @div_unsigned_dynamic(%arg0: memref<?x?x?xi32>, %arg1: memref<?x?x?xi32>, %arg2: memref<?x?x?xi32>) {
- // CHECK: linalg.div_unsigned
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<?x?x?xi32>, memref<?x?x?xi32>)
- // CHECK-SAME: outs(%{{.+}} : memref<?x?x?xi32>)
- linalg.div_unsigned ins(%arg0, %arg1 : memref<?x?x?xi32>, memref<?x?x?xi32>) outs(%arg2: memref<?x?x?xi32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @div_unsigned_static
-func.func @div_unsigned_static(%arg0: memref<4x8x16xi32>, %arg1: memref<4x8x16xi32>, %arg2: memref<4x8x16xi32>) {
- // CHECK: linalg.div_unsigned
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<4x8x16xi32>, memref<4x8x16xi32>)
- // CHECK-SAME: outs(%{{.+}} : memref<4x8x16xi32>)
- linalg.div_unsigned ins(%arg0, %arg1 : memref<4x8x16xi32>, memref<4x8x16xi32>) outs(%arg2: memref<4x8x16xi32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @div_unsigned_tensor
-func.func @div_unsigned_tensor(%arg0: tensor<4x8x16xi32>, %arg1: tensor<4x8x16xi32>) -> tensor<4x8x16xi32> {
- %0 = tensor.empty() : tensor<4x8x16xi32>
- // CHECK: linalg.div_unsigned
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : tensor<4x8x16xi32>, tensor<4x8x16xi32>)
- // CHECK-SAME: outs(%{{.+}} : tensor<4x8x16xi32>)
- %1 = linalg.div_unsigned ins(%arg0, %arg1 : tensor<4x8x16xi32>, tensor<4x8x16xi32>) outs(%0: tensor<4x8x16xi32>) -> tensor<4x8x16xi32>
- return %1 : tensor<4x8x16xi32>
-}
-
-// -----
-
-// 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
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<?x?x?xf32>, memref<?x?x?xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<?x?x?xf32>)
- linalg.max ins(%arg0, %arg1 : memref<?x?x?xf32>, memref<?x?x?xf32>) outs(%arg2: memref<?x?x?xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @max_static
-func.func @max_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: linalg.max
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<4x8x16xf32>, memref<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<4x8x16xf32>)
- linalg.max ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @max_tensor
-func.func @max_tensor(%arg0: tensor<4x8x16xf32>, %arg1: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
- %0 = tensor.empty() : tensor<4x8x16xf32>
- // CHECK: linalg.max
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : tensor<4x8x16xf32>, tensor<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : tensor<4x8x16xf32>)
- %1 = linalg.max ins(%arg0, %arg1 : tensor<4x8x16xf32>, tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
- return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @min_dynamic
-func.func @min_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>, %arg2: memref<?x?x?xf32>) {
- // CHECK: linalg.min
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<?x?x?xf32>, memref<?x?x?xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<?x?x?xf32>)
- linalg.min ins(%arg0, %arg1 : memref<?x?x?xf32>, memref<?x?x?xf32>) outs(%arg2: memref<?x?x?xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @min_static
-func.func @min_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: linalg.min
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<4x8x16xf32>, memref<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<4x8x16xf32>)
- linalg.min ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @min_tensor
-func.func @min_tensor(%arg0: tensor<4x8x16xf32>, %arg1: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
- %0 = tensor.empty() : tensor<4x8x16xf32>
- // CHECK: linalg.min
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : tensor<4x8x16xf32>, tensor<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : tensor<4x8x16xf32>)
- %1 = linalg.min ins(%arg0, %arg1 : tensor<4x8x16xf32>, tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
- return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @powf_dynamic
-func.func @powf_dynamic(%arg0: memref<?x?x?xf32>, %arg1: memref<?x?x?xf32>, %arg2: memref<?x?x?xf32>) {
- // CHECK: linalg.powf
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<?x?x?xf32>, memref<?x?x?xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<?x?x?xf32>)
- linalg.powf ins(%arg0, %arg1 : memref<?x?x?xf32>, memref<?x?x?xf32>) outs(%arg2: memref<?x?x?xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @powf_static
-func.func @powf_static(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>) {
- // CHECK: linalg.powf
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : memref<4x8x16xf32>, memref<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : memref<4x8x16xf32>)
- linalg.powf ins(%arg0, %arg1 : memref<4x8x16xf32>, memref<4x8x16xf32>) outs(%arg2: memref<4x8x16xf32>)
- return
-}
-
-// -----
-
-// CHECK-LABEL: func @powf_tensor
-func.func @powf_tensor(%arg0: tensor<4x8x16xf32>, %arg1: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> {
- %0 = tensor.empty() : tensor<4x8x16xf32>
- // CHECK: linalg.powf
- // CHECK-SAME: ins(%{{.+}}, %{{.+}} : tensor<4x8x16xf32>, tensor<4x8x16xf32>)
- // CHECK-SAME: outs(%{{.+}} : tensor<4x8x16xf32>)
- %1 = linalg.powf ins(%arg0, %arg1 : tensor<4x8x16xf32>, tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32>
- return %1 : tensor<4x8x16xf32>
-}
-
-// -----
-
// CHECK-LABEL: func @fill_tensor
func.func @fill_tensor(%f: f32, %v: vector<2x4xf32>) -> (tensor<f32>, tensor<vector<2x4xf32>>) {
%e0 = tensor.empty() : tensor<f32>
diff --git a/mlir/test/Dialect/Linalg/reshape_fusion.mlir b/mlir/test/Dialect/Linalg/reshape_fusion.mlir
index 3fb7225069983..12980faa00f7e 100644
--- a/mlir/test/Dialect/Linalg/reshape_fusion.mlir
+++ b/mlir/test/Dialect/Linalg/reshape_fusion.mlir
@@ -688,7 +688,7 @@ func.func @linalg_add_reshape_consumer_fusion(%arg0 : tensor<?x?xf32>,
%sz1: index) ->
tensor<?x?x4x5xf32>
{
- %0 = linalg.add ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
+ %0 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg2 : tensor<?x?xf32>) -> tensor<?x?xf32>
%1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, %sz1, 4, 5] :
tensor<?x?xf32> into tensor<?x?x4x5xf32>
@@ -720,7 +720,7 @@ func.func @linalg_add_reshape_producer_fusion(%arg0 : tensor<?x7x?x8xf32>,
{
%0 = tensor.collapse_shape %arg0 [[0, 1], [2, 3]] :
tensor<?x7x?x8xf32> into tensor<?x?xf32>
- %1 = linalg.add ins(%0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
+ %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg2 : tensor<?x?xf32>) -> tensor<?x?xf32>
return %1 : tensor<?x?xf32>
}
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 0edf9d7bb7ded..913ca280c2620 100644
--- a/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-named-ops.mlir
+++ b/mlir/test/Dialect/Linalg/roundtrip-morphism-linalg-named-ops.mlir
@@ -5,143 +5,6 @@
// RUN: | mlir-opt -split-input-file -linalg-morph-ops=generic-to-named \
// RUN: | FileCheck %s
-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>)
- linalg.sub ins(%A, %B : memref<10xi32>, memref<10xi32>) outs(%Out : memref<10xi32>)
- linalg.mul ins(%A, %B : memref<10xi32>, memref<10xi32>) outs(%Out : memref<10xi32>)
- linalg.div ins(%A, %B : memref<10xi32>, memref<10xi32>) outs(%Out : memref<10xi32>)
- linalg.div_unsigned ins(%A, %B : memref<10xi32>, memref<10xi32>) outs(%Out : memref<10xi32>)
- linalg.max ins(%A, %B : memref<10xi32>, memref<10xi32>) outs(%Out : memref<10xi32>)
- linalg.min ins(%A, %B : memref<10xi32>, memref<10xi32>) outs(%Out : memref<10xi32>)
- return
-}
-
-// CHECK-LABEL: binary_ops_int
-// CHECK-SAME: %[[A:.+]]: memref<10xi32>, %[[B:.+]]: memref<10xi32>,
-// CHECK-SAME: %[[OUT:.+]]: memref<10xi32>)
-// CHECK-NOT: linalg.generic
-// CHECK: linalg.add
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xi32>, memref<10xi32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xi32>)
-// CHECK: linalg.sub
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xi32>, memref<10xi32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xi32>)
-// CHECK: linalg.mul
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xi32>, memref<10xi32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xi32>)
-// CHECK: linalg.div
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xi32>, memref<10xi32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xi32>)
-// CHECK: linalg.div_unsigned
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xi32>, memref<10xi32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xi32>)
-// CHECK: linalg.max
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xi32>, memref<10xi32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xi32>)
-// CHECK: linalg.min
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xi32>, memref<10xi32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xi32>)
-
-// -----
-
-func.func @binary_ops_float(%A: memref<10xf32>, %B: memref<10xf32>,
- %Out: memref<10xf32>) {
- linalg.add ins(%A, %B : memref<10xf32>, memref<10xf32>) outs(%Out : memref<10xf32>)
- linalg.sub ins(%A, %B : memref<10xf32>, memref<10xf32>) outs(%Out : memref<10xf32>)
- linalg.mul ins(%A, %B : memref<10xf32>, memref<10xf32>) outs(%Out : memref<10xf32>)
- linalg.div ins(%A, %B : memref<10xf32>, memref<10xf32>) outs(%Out : memref<10xf32>)
- linalg.max ins(%A, %B : memref<10xf32>, memref<10xf32>) outs(%Out : memref<10xf32>)
- linalg.min ins(%A, %B : memref<10xf32>, memref<10xf32>) outs(%Out : memref<10xf32>)
- linalg.powf ins(%A, %B : memref<10xf32>, memref<10xf32>) outs(%Out : memref<10xf32>)
- return
-}
-
-// CHECK-LABEL: binary_ops_float
-// CHECK-SAME: %[[A:.+]]: memref<10xf32>, %[[B:.+]]: memref<10xf32>,
-// CHECK-SAME: %[[OUT:.+]]: memref<10xf32>)
-// CHECK-NOT: linalg.generic
-// CHECK: linalg.add
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xf32>, memref<10xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xf32>)
-// CHECK: linalg.sub
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xf32>, memref<10xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xf32>)
-// CHECK: linalg.mul
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xf32>, memref<10xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xf32>)
-// CHECK: linalg.div
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xf32>, memref<10xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xf32>)
-// CHECK: linalg.max
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xf32>, memref<10xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xf32>)
-// CHECK: linalg.min
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xf32>, memref<10xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xf32>)
-// CHECK: linalg.powf
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xf32>, memref<10xf32>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xf32>)
-
-// -----
-
-func.func @binary_ops_complex(%A: memref<10xcomplex<f32>>, %B: memref<10xcomplex<f32>>,
- %Out: memref<10xcomplex<f32>>) {
- linalg.add ins(%A, %B : memref<10xcomplex<f32>>, memref<10xcomplex<f32>>)
- outs(%Out : memref<10xcomplex<f32>>)
- linalg.sub ins(%A, %B : memref<10xcomplex<f32>>, memref<10xcomplex<f32>>)
- outs(%Out : memref<10xcomplex<f32>>)
- linalg.mul ins(%A, %B : memref<10xcomplex<f32>>, memref<10xcomplex<f32>>)
- outs(%Out : memref<10xcomplex<f32>>)
- linalg.div ins(%A, %B : memref<10xcomplex<f32>>, memref<10xcomplex<f32>>)
- outs(%Out : memref<10xcomplex<f32>>)
- return
-}
-
-// CHECK-LABEL: binary_ops_complex
-// CHECK-SAME: %[[A:.+]]: memref<10xcomplex<f32>>, %[[B:.+]]: memref<10xcomplex<f32>>,
-// CHECK-SAME: %[[OUT:.+]]: memref<10xcomplex<f32>>)
-// CHECK-NOT: linalg.generic
-// CHECK: linalg.add
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xcomplex<f32>>, memref<10xcomplex<f32>>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xcomplex<f32>>)
-// CHECK: linalg.sub
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xcomplex<f32>>, memref<10xcomplex<f32>>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xcomplex<f32>>)
-// CHECK: linalg.mul
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xcomplex<f32>>, memref<10xcomplex<f32>>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xcomplex<f32>>)
-// CHECK: linalg.div
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xcomplex<f32>>, memref<10xcomplex<f32>>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xcomplex<f32>>)
-
-// -----
-
-func.func @binary_ops_bool(%A: memref<10xi1>, %B: memref<10xi1>,
- %Out: memref<10xi1>) {
- linalg.add ins(%A, %B : memref<10xi1>, memref<10xi1>) outs(%Out : memref<10xi1>)
- linalg.mul ins(%A, %B : memref<10xi1>, memref<10xi1>) outs(%Out : memref<10xi1>)
- return
-}
-
-// CHECK-LABEL: binary_ops_bool
-// CHECK-SAME: %[[A:.+]]: memref<10xi1>, %[[B:.+]]: memref<10xi1>,
-// CHECK-SAME: %[[OUT:.+]]: memref<10xi1>)
-// CHECK-NOT: linalg.generic
-// CHECK: linalg.add
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xi1>, memref<10xi1>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xi1>)
-// CHECK: linalg.mul
-// CHECK-SAME: ins(%[[A]], %[[B]] : memref<10xi1>, memref<10xi1>)
-// CHECK-SAME: outs(%[[OUT]] : memref<10xi1>)
-
-// -----
-
-
-///----------------------------------------------------------------------------------------
-/// Tests for linalg.matmul
-///----------------------------------------------------------------------------------------
-
func.func @matmul(%A: tensor<?x?xf32>, %B: tensor<?x?xf32>,
%Out: tensor<?x?xf32>) -> tensor<?x?xf32> {
%0 = linalg.matmul
@@ -192,26 +55,3 @@ func.func @matmul_unsigned_cast(%A: tensor<16x8xi16>, %B: tensor<8x32xi64>,
// CHECK: linalg.matmul
// CHECK-SAME: {cast = #linalg.type_fn<cast_unsigned>}
-// -----
-
-func.func @mixed_named_ops(%A: tensor<?x?xf32>, %B: tensor<?x?xf32>,
- %C: tensor<?x?xf32>, %Out: tensor<?x?xf32>) -> tensor<?x?xf32> {
- %AB = linalg.matmul
- ins(%A, %B : tensor<?x?xf32>, tensor<?x?xf32>)
- outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
- %1 = linalg.add
- ins(%AB, %C : tensor<?x?xf32>, tensor<?x?xf32>)
- outs(%Out : tensor<?x?xf32>) -> tensor<?x?xf32>
- return %1 : tensor<?x?xf32>
-}
-
-// CHECK-LABEL: @mixed_named_ops
-// CHECK-SAME: %[[A:.+]]: tensor<?x?xf32>, %[[B:.+]]: tensor<?x?xf32>, %[[C:.+]]: tensor<?x?xf32>,
-// CHECK-SAME: %[[OUT:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK-NOT: linalg.generic
-// CHECK: %[[AB:.+]] = linalg.matmul
-// CHECK-SAME: ins(%[[A]], %[[B]] : tensor<?x?xf32>, tensor<?x?xf32>)
-// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK: linalg.add
-// CHECK-SAME: ins(%[[AB]], %[[C]] : tensor<?x?xf32>, tensor<?x?xf32>)
-// CHECK-SAME: outs(%[[OUT]] : tensor<?x?xf32>) -> tensor<?x?xf32>
diff --git a/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir b/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir
index 01e06908c32d5..ddd3f4a543f85 100644
--- a/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir
+++ b/mlir/test/Dialect/Linalg/specialize-generic-ops.mlir
@@ -263,19 +263,10 @@ func.func @unary_ops_non_identity(%A: tensor<?xf32>, %Out: tensor<?x?xf32>) -> t
#map = affine_map<(d0, d1) -> (d0, d1)>
func.func @binary_ops_int(%A: tensor<?x?xi32>, %B: tensor<?x?xi32>,
%Out: tensor<?x?xi32>) -> tensor<?x?xi32> {
- %0 = linalg.generic
- {indexing_maps = [#map, #map, #map],
- iterator_types = ["parallel", "parallel"]}
- ins(%A, %B : tensor<?x?xi32>, tensor<?x?xi32>)
- outs(%Out : tensor<?x?xi32>) {
- ^bb0(%in: i32, %in_0: i32, %out: i32):
- %v = arith.addi %in, %in_0 : i32
- linalg.yield %v : i32
- } -> tensor<?x?xi32>
%1 = linalg.generic
{indexing_maps = [#map, #map, #map],
iterator_types = ["parallel", "parallel"]}
- ins(%0, %B : tensor<?x?xi32>, tensor<?x?xi32>)
+ ins(%A, %B : tensor<?x?xi32>, tensor<?x?xi32>)
outs(%Out : tensor<?x?xi32>) {
^bb0(%in: i32, %in_0: i32, %out: i32):
%v = arith.subi %in, %in_0 : i32
@@ -334,34 +325,28 @@ func.func @binary_ops_int(%A: tensor<?x?xi32>, %B: tensor<?x?xi32>,
// ALL-SAME: %[[OUT:.+]]: [[TTY]]) -> [[TTY]]
// NAMED-NOT: linalg.generic
-// NAMED: %[[RES0:.+]] = linalg.add
+// NAMED: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<sub>
// NAMED-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES1:.+]] = linalg.sub
-// NAMED-SAME: ins(%[[RES0]], %[[B]] : [[TTY]], [[TTY]])
-// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES2:.+]] = linalg.mul
+// NAMED: %[[RES2:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// NAMED-SAME: ins(%[[RES1]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES3:.+]] = linalg.div
+// NAMED: %[[RES3:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<div>
// NAMED-SAME: ins(%[[RES2]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES4:.+]] = linalg.div_unsigned
+// NAMED: %[[RES4:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<div_unsigned>
// NAMED-SAME: ins(%[[RES3]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES5:.+]] = linalg.max
+// NAMED: %[[RES5:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<max_signed>
// NAMED-SAME: ins(%[[RES4]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES6:.+]] = linalg.min
+// NAMED: %[[RES6:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<min_signed>
// NAMED-SAME: ins(%[[RES5]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY-NOT: linalg.generic
-// CATEGORY: %[[RES0:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<add>
-// CATEGORY-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
-// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<sub>
-// CATEGORY-SAME: ins(%[[RES0]], %[[B]] : [[TTY]], [[TTY]])
+// CATEGORY-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY: %[[RES2:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// CATEGORY-SAME: ins(%[[RES1]], %[[B]] : [[TTY]], [[TTY]])
@@ -384,19 +369,10 @@ func.func @binary_ops_int(%A: tensor<?x?xi32>, %B: tensor<?x?xi32>,
#map = affine_map<(d0, d1) -> (d0, d1)>
func.func @binary_ops_float(%A: tensor<?x?xf32>, %B: tensor<?x?xf32>,
%Out: tensor<?x?xf32>) -> tensor<?x?xf32> {
- %0 = linalg.generic
- {indexing_maps = [#map, #map, #map],
- iterator_types = ["parallel", "parallel"]}
- ins(%A, %B : tensor<?x?xf32>, tensor<?x?xf32>)
- outs(%Out : tensor<?x?xf32>) {
- ^bb0(%in: f32, %in_0: f32, %out: f32):
- %v = arith.addf %in, %in_0 : f32
- linalg.yield %v : f32
- } -> tensor<?x?xf32>
%1 = linalg.generic
{indexing_maps = [#map, #map, #map],
iterator_types = ["parallel", "parallel"]}
- ins(%0, %B : tensor<?x?xf32>, tensor<?x?xf32>)
+ ins(%A, %B : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%Out : tensor<?x?xf32>) {
^bb0(%in: f32, %in_0: f32, %out: f32):
%v = arith.subf %in, %in_0 : f32
@@ -455,34 +431,28 @@ func.func @binary_ops_float(%A: tensor<?x?xf32>, %B: tensor<?x?xf32>,
// ALL-SAME: %[[OUT:.+]]: [[TTY]]) -> [[TTY]]
// NAMED-NOT: linalg.generic
-// NAMED: %[[RES0:.+]] = linalg.add
+// NAMED: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<sub>
// NAMED-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES1:.+]] = linalg.sub
-// NAMED-SAME: ins(%[[RES0]], %[[B]] : [[TTY]], [[TTY]])
-// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES2:.+]] = linalg.mul
+// NAMED: %[[RES2:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// NAMED-SAME: ins(%[[RES1]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES3:.+]] = linalg.div
+// NAMED: %[[RES3:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<div>
// NAMED-SAME: ins(%[[RES2]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES4:.+]] = linalg.max
+// NAMED: %[[RES4:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<max_signed>
// NAMED-SAME: ins(%[[RES3]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES5:.+]] = linalg.min
+// NAMED: %[[RES5:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<min_signed>
// NAMED-SAME: ins(%[[RES4]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES6:.+]] = linalg.powf
+// NAMED: %[[RES6:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<powf>
// NAMED-SAME: ins(%[[RES5]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY-NOT: linalg.generic
-// CATEGORY: %[[RES0:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<add>
-// CATEGORY-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
-// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<sub>
-// CATEGORY-SAME: ins(%[[RES0]], %[[B]] : [[TTY]], [[TTY]])
+// CATEGORY-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY: %[[RES2:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// CATEGORY-SAME: ins(%[[RES1]], %[[B]] : [[TTY]], [[TTY]])
@@ -507,19 +477,10 @@ func.func @binary_ops_complex(%A: tensor<?x?xcomplex<f32>>,
%B: tensor<?x?xcomplex<f32>>,
%Out: tensor<?x?xcomplex<f32>>)
-> tensor<?x?xcomplex<f32>> {
- %0 = linalg.generic
- {indexing_maps = [#map, #map, #map],
- iterator_types = ["parallel", "parallel"]}
- ins(%A, %B : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>)
- outs(%Out : tensor<?x?xcomplex<f32>>) {
- ^bb0(%in: complex<f32>, %in_0: complex<f32>, %out: complex<f32>):
- %v = complex.add %in, %in_0 : complex<f32>
- linalg.yield %v : complex<f32>
- } -> tensor<?x?xcomplex<f32>>
%1 = linalg.generic
{indexing_maps = [#map, #map, #map],
iterator_types = ["parallel", "parallel"]}
- ins(%0, %B : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>)
+ ins(%A, %B : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>)
outs(%Out : tensor<?x?xcomplex<f32>>) {
^bb0(%in: complex<f32>, %in_0: complex<f32>, %out: complex<f32>):
%v = complex.sub %in, %in_0 : complex<f32>
@@ -551,25 +512,19 @@ func.func @binary_ops_complex(%A: tensor<?x?xcomplex<f32>>,
// ALL-SAME: %[[OUT:.+]]: [[TTY]]) -> [[TTY]]
// NAMED-NOT: linalg.generic
-// NAMED: %[[RES0:.+]] = linalg.add
+// NAMED: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<sub>
// NAMED-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES1:.+]] = linalg.sub
-// NAMED-SAME: ins(%[[RES0]], %[[B]] : [[TTY]], [[TTY]])
-// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES2:.+]] = linalg.mul
+// NAMED: %[[RES2:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// NAMED-SAME: ins(%[[RES1]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES3:.+]] = linalg.div
+// NAMED: %[[RES3:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<div>
// NAMED-SAME: ins(%[[RES2]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY-NOT: linalg.generic
-// CATEGORY: %[[RES0:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<add>
-// CATEGORY-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
-// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<sub>
-// CATEGORY-SAME: ins(%[[RES0]], %[[B]] : [[TTY]], [[TTY]])
+// CATEGORY-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY: %[[RES2:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// CATEGORY-SAME: ins(%[[RES1]], %[[B]] : [[TTY]], [[TTY]])
@@ -583,19 +538,10 @@ func.func @binary_ops_complex(%A: tensor<?x?xcomplex<f32>>,
#map = affine_map<(d0, d1) -> (d0, d1)>
func.func @binary_ops_bool(%A: tensor<?x?xi1>, %B: tensor<?x?xi1>,
%Out: tensor<?x?xi1>) -> tensor<?x?xi1> {
- %0 = linalg.generic
- {indexing_maps = [#map, #map, #map],
- iterator_types = ["parallel", "parallel"]}
- ins(%A, %B : tensor<?x?xi1>, tensor<?x?xi1>)
- outs(%Out : tensor<?x?xi1>) {
- ^bb0(%in: i1, %in_0: i1, %out: i1):
- %v = arith.ori %in, %in_0 : i1
- linalg.yield %v : i1
- } -> tensor<?x?xi1>
%1 = linalg.generic
{indexing_maps = [#map, #map, #map],
iterator_types = ["parallel", "parallel"]}
- ins(%0, %B : tensor<?x?xi1>, tensor<?x?xi1>)
+ ins(%A, %B : tensor<?x?xi1>, tensor<?x?xi1>)
outs(%Out : tensor<?x?xi1>) {
^bb0(%in: i1, %in_0: i1, %out: i1):
%v = arith.andi %in, %in_0 : i1
@@ -609,19 +555,13 @@ func.func @binary_ops_bool(%A: tensor<?x?xi1>, %B: tensor<?x?xi1>,
// ALL-SAME: %[[OUT:.+]]: [[TTY]]) -> [[TTY]]
// NAMED-NOT: linalg.generic
-// NAMED: %[[RES0:.+]] = linalg.add
+// NAMED: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// NAMED-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES1:.+]] = linalg.mul
-// NAMED-SAME: ins(%[[RES0]], %[[B]] : [[TTY]], [[TTY]])
-// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY-NOT: linalg.generic
-// CATEGORY: %[[RES0:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<add>
-// CATEGORY-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
-// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
-// CATEGORY-SAME: ins(%[[RES0]], %[[B]] : [[TTY]], [[TTY]])
+// CATEGORY-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// -----
@@ -654,18 +594,6 @@ func.func @binary_ops_uint(%A: tensor<?x?xi32>, %B: tensor<?x?xi32>,
// ALL-SAME: %[[A:.+]]: [[TTY:tensor<\?x\?xi32>]], %[[B:.+]]: [[TTY]],
// ALL-SAME: %[[OUT:.+]]: [[TTY]]) -> [[TTY]]
-// No named ops yet for unsigned max/min -> expect no change.
-// NAMED-NOT: linalg.{{max|min}}
-// NAMED: linalg.generic
-
-// CATEGORY-NOT: linalg.generic
-// CATEGORY: %[[RES0:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<max_unsigned>
-// CATEGORY-SAME: ins(%[[A]], %[[B]] : [[TTY]], [[TTY]])
-// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-// CATEGORY: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<min_unsigned>
-// CATEGORY-SAME: ins(%[[RES0]], %[[B]] : [[TTY]], [[TTY]])
-// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
-
// -----
func.func @binary_ops_non_identity(%A: tensor<?xf32>, %B: tensor<?x?xf32>,
@@ -677,7 +605,7 @@ func.func @binary_ops_non_identity(%A: tensor<?xf32>, %B: tensor<?x?xf32>,
ins(%A, %B : tensor<?xf32>, tensor<?x?xf32>)
outs(%Out : tensor<?x?xf32>) {
^bb0(%in: f32, %in_0: f32, %out: f32):
- %v = arith.addf %in, %in_0 : f32
+ %v = arith.subf %in, %in_0 : f32
linalg.yield %v : f32
} -> tensor<?x?xf32>
return %0 : tensor<?x?xf32>
@@ -691,11 +619,11 @@ func.func @binary_ops_non_identity(%A: tensor<?xf32>, %B: tensor<?x?xf32>,
// ALL-SAME: %[[OUT:.+]]: [[TTY]]) -> [[TTY]]
// Named ops cannot carry user-defined indexing maps -> expect no change.
-// NAMED-NOT: linalg.add
+// NAMED-NOT: linalg.sub
// NAMED: linalg.generic
// CATEGORY-NOT: linalg.generic
-// CATEGORY: linalg.elementwise kind=#linalg.elementwise_kind<add>
+// CATEGORY: linalg.elementwise kind=#linalg.elementwise_kind<sub>
// CATEGORY-SAME: indexing_maps = [#[[MAP_BC]], #[[MAP_TP]], #[[MAP_ID]]]
// CATEGORY-SAME: ins(%[[A]], %[[B]] : [[TTY1D]], [[TTY]])
// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
@@ -713,7 +641,7 @@ func.func @binary_ops_swapped(%A: tensor<?x?xf32>, %B: tensor<?x?xf32>,
ins(%A, %B : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%Out : tensor<?x?xf32>) {
^bb0(%in: f32, %in_0: f32, %out: f32):
- %v = arith.addf %in_0, %in : f32
+ %v = arith.mulf %in_0, %in : f32
linalg.yield %v : f32
} -> tensor<?x?xf32>
%1 = linalg.generic
@@ -735,7 +663,7 @@ func.func @binary_ops_swapped(%A: tensor<?x?xf32>, %B: tensor<?x?xf32>,
// ALL-SAME: %[[C:.+]]: [[TTY1D:tensor<\?xf32>]],
// ALL-SAME: %[[OUT:.+]]: [[TTY]]) -> [[TTY]]
-// NAMED: %[[RES0:.+]] = linalg.add
+// NAMED: %[[RES0:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// NAMED-SAME: ins(%[[B]], %[[A]] : [[TTY]], [[TTY]])
// NAMED-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// NAMED-NOT: linalg.sub
@@ -743,7 +671,7 @@ func.func @binary_ops_swapped(%A: tensor<?x?xf32>, %B: tensor<?x?xf32>,
// NAMED-SAME: ins(%[[RES0]], %[[C]] : [[TTY]], [[TTY1D]])
// CATEGORY-NOT: linalg.generic
-// CATEGORY: %[[RES0:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<add>
+// CATEGORY: %[[RES0:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<mul>
// CATEGORY-SAME: ins(%[[B]], %[[A]] : [[TTY]], [[TTY]])
// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
// CATEGORY: %[[RES1:.+]] = linalg.elementwise kind=#linalg.elementwise_kind<sub>
@@ -763,7 +691,7 @@ func.func @unary_op_with_scalar(%A: tensor<?xi32>, %Out: tensor<?xi32>)
ins(%A : tensor<?xi32>)
outs(%Out : tensor<?xi32>) {
^bb0(%in: i32, %out: i32):
- %v = arith.addi %cst, %in : i32
+ %v = arith.subi %cst, %in : i32
linalg.yield %v : i32
} -> tensor<?xi32>
return %0 : tensor<?xi32>
@@ -776,12 +704,12 @@ func.func @unary_op_with_scalar(%A: tensor<?xi32>, %Out: tensor<?xi32>)
// CATEGORY-SAME: %[[OUT:.+]]: [[TTY]]) -> [[TTY]]
// Named ops cannot broadcast from a scalar operand -> expect no change.
-// NAMED-NOT: linalg.add
+// NAMED-NOT: linalg.sub
// NAMED: linalg.generic
// CATEGORY-NOT: linalg.generic
// CATEGORY: %[[CST:.+]] = arith.constant 123 : i32
-// CATEGORY: linalg.elementwise kind=#linalg.elementwise_kind<add>
+// CATEGORY: linalg.elementwise kind=#linalg.elementwise_kind<sub>
// CATEGORY-SAME: indexing_maps = [#[[MAP_BC]], #[[MAP_ID]], #[[MAP_ID]]]
// CATEGORY-SAME: ins(%[[CST]], %[[A]] : i32, [[TTY]])
// CATEGORY-SAME: outs(%[[OUT]] : [[TTY]]) -> [[TTY]]
diff --git a/mlir/test/Dialect/Linalg/transform-op-fuse.mlir b/mlir/test/Dialect/Linalg/transform-op-fuse.mlir
index 438846febdbd4..9517550af42ed 100644
--- a/mlir/test/Dialect/Linalg/transform-op-fuse.mlir
+++ b/mlir/test/Dialect/Linalg/transform-op-fuse.mlir
@@ -5,19 +5,19 @@ func.func @fuse_unary(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<
// CHECK: %[[RES:.*]] = scf.for
// CHECK: scf.for
- // CHECK: linalg.elementwise
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: return %[[RES]]
%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>)
+ %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %1 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%1, %loops:2 = transform.structured.fuse %0 tile_sizes [32, 32] interchange [0, 1]
: (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
transform.yield
@@ -31,23 +31,23 @@ func.func @fuse_unary(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<
// CHECK: %[[PARTIAL_RES:.*]] = scf.for
// CHECK: scf.for
- // CHECK: linalg.elementwise
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: %[[RES:.*]] = scf.for {{.*}}%[[PARTIAL_RES]]
// CHECK: scf.for
- // CHECK: linalg.elementwise
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: return %[[RES]]
%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>)
+ %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %1 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%1, %loops:2 = transform.structured.fuse %0 tile_sizes [32, 32] interchange [0, 1]
: (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">, !transform.any_op)
transform.loop.peel %loops#0 : (!transform.op<"scf.for">) -> (!transform.any_op, !transform.any_op)
@@ -62,19 +62,19 @@ func.func @fuse_unary_param(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> t
// CHECK: %[[RES:.*]] = scf.for
// CHECK: scf.for
- // CHECK: linalg.elementwise
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: return %[[RES]]
%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>)
+ %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %1 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%c32 = transform.param.constant 32 : i32 -> !transform.param<i32>
%c32_as_any = transform.param.constant 32 : i32 -> !transform.any_param
%c1 = transform.param.constant 1 : i32 -> !transform.param<i32>
@@ -91,19 +91,19 @@ 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.elementwise
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: return %[[RES]]
%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>)
+ %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %1 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%1, %loop = transform.structured.fuse %0 tile_sizes [32, 32] {use_forall}
: (!transform.any_op) -> (!transform.any_op, !transform.any_op)
transform.yield
@@ -117,19 +117,19 @@ func.func @fuse_unary_packed_tile_sizes(%arg0: tensor<?x?xf32>, %arg1: tensor<?x
// CHECK: %[[RES:.*]] = scf.for
// CHECK: scf.for
- // CHECK: linalg.elementwise
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: return %[[RES]]
%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>)
+ %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %1 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%c32 = transform.param.constant 32 : i64 -> !transform.any_param
%c64 = transform.param.constant 64 : i64 -> !transform.any_param
%tiles = transform.merge_handles %c32, %c64 : !transform.any_param
@@ -148,19 +148,19 @@ 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.elementwise
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: return %[[RES]]
%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>)
+ %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %1 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%c32 = transform.param.constant 32 : i64 -> !transform.any_param
%c64 = transform.param.constant 64 : i64 -> !transform.any_param
%tiles = transform.merge_handles %c32, %c64 : !transform.any_param
@@ -181,21 +181,21 @@ func.func @fuse_unary_packed_tile_sizes_multiple_targets(
// CHECK: scf.for
// CHECK: scf.for
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise
// CHECK: %[[RES:.*]] = scf.for
// CHECK: scf.for
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise
// CHECK: return %[[RES]]
- %0 = linalg.add ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
+ %0 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
- %1 = linalg.add ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
+ %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %1 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%c32 = transform.param.constant 32 : i64 -> !transform.any_param
%c64 = transform.param.constant 64 : i64 -> !transform.any_param
%tiles = transform.merge_handles %c32, %c64 : !transform.any_param
@@ -214,19 +214,19 @@ 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.elementwise
- // CHECK: %[[RES:.*]] = linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: %[[RES:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: return %[[RES]]
%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>)
+ %1 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg0 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %1 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%c0 = transform.param.constant 0 : i64 -> !transform.any_param
%tiles = transform.merge_handles %c0, %c0 : !transform.any_param
%1, %loops = transform.structured.fuse %0 tile_sizes *(%tiles)
@@ -366,8 +366,8 @@ func.func @fuse_through_slice(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) ->
// CHECK: %[[RES:.*]] = scf.for
// CHECK: scf.for
- // CHECK: linalg.elementwise
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: return %[[RES]]
%0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<?x?xf32>)
outs(%arg0: tensor<?x?xf32>) -> tensor<?x?xf32>
@@ -376,14 +376,14 @@ func.func @fuse_through_slice(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>) ->
%dim0 = tensor.dim %arg1, %c0 : tensor<?x?xf32>
%dim1 = tensor.dim %arg1, %c1 : 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>)
+ %2 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%1, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %2 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%1, %loops:2 = transform.structured.fuse %0 tile_sizes [32, 32] interchange [0, 1] {apply_cleanup}
: (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">, !transform.any_op)
transform.yield
@@ -397,8 +397,8 @@ func.func @fuse_through_slice_and_cast_chain(%arg0: tensor<100x100xf32>, %arg1:
// CHECK: %[[RES:.*]] = scf.for
// CHECK: scf.for
- // CHECK: linalg.elementwise
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: return %[[RES]]
%0 = linalg.elementwise kind=#linalg.elementwise_kind<exp> ins(%arg0 : tensor<100x100xf32>)
outs(%arg0: tensor<100x100xf32>) -> tensor<100x100xf32>
@@ -410,14 +410,14 @@ func.func @fuse_through_slice_and_cast_chain(%arg0: tensor<100x100xf32>, %arg1:
%dim0 = tensor.dim %arg1, %c0 : tensor<?x?xf32>
%dim1 = tensor.dim %arg1, %c1 : tensor<?x?xf32>
%4 = tensor.extract_slice %3 [1, 1] [%dim0, %dim1] [1, 1] : tensor<?x?xf32> to tensor<?x?xf32>
- %5 = linalg.add ins(%4, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
+ %5 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%4, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %5 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%1, %loops:2 = transform.structured.fuse %0 tile_sizes [32, 32] interchange [0, 1] {apply_cleanup}
: (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">, !transform.any_op)
transform.yield
@@ -433,8 +433,8 @@ 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.elementwise
- // CHECK: linalg.add
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<exp>
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add>
// CHECK: return %[[RES]], %[[SLICE2]]
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
@@ -445,14 +445,14 @@ func.func @fuse_unrelated_slices(%arg0: tensor<?x?xf32>, %arg1: 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>)
+ %2 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%1, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
outs(%arg1: tensor<?x?xf32>) -> tensor<?x?xf32>
return %2, %slice2 : tensor<?x?xf32>, tensor<10x10xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<add>} in %arg1 : (!transform.any_op) -> !transform.any_op
%1, %loops:2 = transform.structured.fuse %0 tile_sizes [32, 32] interchange [0, 1] {apply_cleanup}
: (!transform.any_op) -> (!transform.any_op, !transform.op<"scf.for">, !transform.any_op)
transform.yield
diff --git a/mlir/test/Dialect/Linalg/transform-op-rewrite-in-destination-passing-style.mlir b/mlir/test/Dialect/Linalg/transform-op-rewrite-in-destination-passing-style.mlir
index 38be8aad98de7..167bbc661794b 100644
--- a/mlir/test/Dialect/Linalg/transform-op-rewrite-in-destination-passing-style.mlir
+++ b/mlir/test/Dialect/Linalg/transform-op-rewrite-in-destination-passing-style.mlir
@@ -257,17 +257,17 @@ module attributes {transform.with_named_sequence} {
// CHECK-LABEL: func @already_destination_passing_style(
// CHECK-SAME: %[[ARG0:.*]]: tensor<134217728xf32>, %[[ARG1:.*]]: tensor<134217728xf32>) -> tensor<134217728xf32>
-// CHECK: %[[RESULT:.*]] = linalg.add ins(%[[ARG0]], %[[ARG1]] : tensor<134217728xf32>, tensor<134217728xf32>)
+// CHECK: %[[RESULT:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%[[ARG0]], %[[ARG1]] : tensor<134217728xf32>, tensor<134217728xf32>)
// CHECK-SAME: outs(%[[ARG0]] : tensor<134217728xf32>) -> tensor<134217728xf32>
// CHECK: return %[[RESULT]] : tensor<134217728xf32>
func.func @already_destination_passing_style(%arg0: tensor<134217728xf32>, %arg1: tensor<134217728xf32>) -> tensor<134217728xf32> {
- %0 = linalg.add ins(%arg0, %arg1 : tensor<134217728xf32>, tensor<134217728xf32>) outs(%arg0 : tensor<134217728xf32>) -> tensor<134217728xf32>
+ %0 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%arg0, %arg1 : tensor<134217728xf32>, tensor<134217728xf32>) outs(%arg0 : tensor<134217728xf32>) -> tensor<134217728xf32>
return %0 : tensor<134217728xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.add"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+ %0 = transform.structured.match ops{["linalg.elementwise"]} in %arg0 : (!transform.any_op) -> !transform.any_op
%1 = transform.structured.rewrite_in_destination_passing_style %0 : (!transform.any_op) -> !transform.any_op
transform.yield
}
diff --git a/mlir/test/Dialect/Linalg/transform-op-specialize-elemwise-binary.mlir b/mlir/test/Dialect/Linalg/transform-op-specialize-elemwise-binary.mlir
index 0f444a2d6a71b..943ebd9ba0be4 100644
--- a/mlir/test/Dialect/Linalg/transform-op-specialize-elemwise-binary.mlir
+++ b/mlir/test/Dialect/Linalg/transform-op-specialize-elemwise-binary.mlir
@@ -1,19 +1,6 @@
// RUN: mlir-opt --transform-interpreter --split-input-file --verify-diagnostics %s | FileCheck %s
#map = affine_map<(d0, d1) -> (d0, d1)>
-func.func @specialize_add_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %arg2: tensor<?x?xi32>) -> tensor<?x?xi32> {
- %0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xi32>, tensor<?x?xi32>) outs(%arg2 : tensor<?x?xi32>) {
- ^bb0(%in: i32, %in_0: i32, %out: i32):
- %1 = arith.addi %in, %in_0 : i32
- linalg.yield %1 : i32
- } -> tensor<?x?xi32>
- return %0 : tensor<?x?xi32>
-}
-// CHECK-LABEL: specialize_add_int
-// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xi32>, %[[ARG1:.+]]: tensor<?x?xi32>, %[[ARG2:.+]]: tensor<?x?xi32>) -> tensor<?x?xi32>
-// CHECK-NOT: linalg.generic
-// CHECK: linalg.add ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
-
func.func @specialize_sub_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %arg2: tensor<?x?xi32>) -> tensor<?x?xi32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xi32>, tensor<?x?xi32>) outs(%arg2 : tensor<?x?xi32>) {
^bb0(%in: i32, %in_0: i32, %out: i32):
@@ -25,7 +12,7 @@ func.func @specialize_sub_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %a
// CHECK-LABEL: specialize_sub_int
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xi32>, %[[ARG1:.+]]: tensor<?x?xi32>, %[[ARG2:.+]]: tensor<?x?xi32>) -> tensor<?x?xi32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.sub ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<sub> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
func.func @specialize_mul_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %arg2: tensor<?x?xi32>) -> tensor<?x?xi32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xi32>, tensor<?x?xi32>) outs(%arg2 : tensor<?x?xi32>) {
@@ -38,7 +25,7 @@ func.func @specialize_mul_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %a
// CHECK-LABEL: specialize_mul_int
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xi32>, %[[ARG1:.+]]: tensor<?x?xi32>, %[[ARG2:.+]]: tensor<?x?xi32>) -> tensor<?x?xi32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.mul ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<mul> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
func.func @specialize_div_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %arg2: tensor<?x?xi32>) -> tensor<?x?xi32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xi32>, tensor<?x?xi32>) outs(%arg2 : tensor<?x?xi32>) {
@@ -51,7 +38,7 @@ func.func @specialize_div_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %a
// CHECK-LABEL: specialize_div_int
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xi32>, %[[ARG1:.+]]: tensor<?x?xi32>, %[[ARG2:.+]]: tensor<?x?xi32>) -> tensor<?x?xi32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.div ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<div> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
func.func @specialize_div_unsigned_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %arg2: tensor<?x?xi32>) -> tensor<?x?xi32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xi32>, tensor<?x?xi32>) outs(%arg2 : tensor<?x?xi32>) {
@@ -64,7 +51,7 @@ func.func @specialize_div_unsigned_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?
// CHECK-LABEL: specialize_div_unsigned_int
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xi32>, %[[ARG1:.+]]: tensor<?x?xi32>, %[[ARG2:.+]]: tensor<?x?xi32>) -> tensor<?x?xi32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.div_unsigned ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<div_unsigned> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
func.func @specialize_max_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %arg2: tensor<?x?xi32>) -> tensor<?x?xi32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xi32>, tensor<?x?xi32>) outs(%arg2 : tensor<?x?xi32>) {
@@ -77,7 +64,7 @@ func.func @specialize_max_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %a
// CHECK-LABEL: specialize_max_int
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xi32>, %[[ARG1:.+]]: tensor<?x?xi32>, %[[ARG2:.+]]: tensor<?x?xi32>) -> tensor<?x?xi32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.max ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<max_signed> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
func.func @specialize_min_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %arg2: tensor<?x?xi32>) -> tensor<?x?xi32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xi32>, tensor<?x?xi32>) outs(%arg2 : tensor<?x?xi32>) {
@@ -90,20 +77,7 @@ func.func @specialize_min_int(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?xi32>, %a
// CHECK-LABEL: specialize_min_int
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xi32>, %[[ARG1:.+]]: tensor<?x?xi32>, %[[ARG2:.+]]: tensor<?x?xi32>) -> tensor<?x?xi32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.min ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
-
-func.func @specialize_add_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>, %arg2: tensor<?x?xf32>) -> tensor<?x?xf32> {
- %0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%arg2 : tensor<?x?xf32>) {
- ^bb0(%in: f32, %in_0: f32, %out: f32):
- %1 = arith.addf %in, %in_0 : f32
- linalg.yield %1 : f32
- } -> tensor<?x?xf32>
- return %0 : tensor<?x?xf32>
-}
-// CHECK-LABEL: specialize_add_float
-// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xf32>, %[[ARG1:.+]]: tensor<?x?xf32>, %[[ARG2:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
-// CHECK-NOT: linalg.generic
-// CHECK: linalg.add ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<min_signed> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi32>, tensor<?x?xi32>) outs(%[[ARG2]] : tensor<?x?xi32>) -> tensor<?x?xi32>
func.func @specialize_sub_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>, %arg2: tensor<?x?xf32>) -> tensor<?x?xf32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%arg2 : tensor<?x?xf32>) {
@@ -116,7 +90,7 @@ func.func @specialize_sub_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>,
// CHECK-LABEL: specialize_sub_float
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xf32>, %[[ARG1:.+]]: tensor<?x?xf32>, %[[ARG2:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.sub ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<sub> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
func.func @specialize_mul_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>, %arg2: tensor<?x?xf32>) -> tensor<?x?xf32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%arg2 : tensor<?x?xf32>) {
@@ -129,7 +103,7 @@ func.func @specialize_mul_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>,
// CHECK-LABEL: specialize_mul_float
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xf32>, %[[ARG1:.+]]: tensor<?x?xf32>, %[[ARG2:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.mul ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<mul> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
func.func @specialize_div_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>, %arg2: tensor<?x?xf32>) -> tensor<?x?xf32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%arg2 : tensor<?x?xf32>) {
@@ -142,7 +116,7 @@ func.func @specialize_div_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>,
// CHECK-LABEL: specialize_div_float
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xf32>, %[[ARG1:.+]]: tensor<?x?xf32>, %[[ARG2:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.div ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<div> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
func.func @specialize_max_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>, %arg2: tensor<?x?xf32>) -> tensor<?x?xf32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%arg2 : tensor<?x?xf32>) {
@@ -155,7 +129,7 @@ func.func @specialize_max_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>,
// CHECK-LABEL: specialize_max_float
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xf32>, %[[ARG1:.+]]: tensor<?x?xf32>, %[[ARG2:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.max ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<max_signed> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
func.func @specialize_min_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>, %arg2: tensor<?x?xf32>) -> tensor<?x?xf32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%arg2 : tensor<?x?xf32>) {
@@ -168,7 +142,7 @@ func.func @specialize_min_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>,
// CHECK-LABEL: specialize_min_float
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xf32>, %[[ARG1:.+]]: tensor<?x?xf32>, %[[ARG2:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.min ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<min_signed> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
func.func @specialize_powf_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>, %arg2: tensor<?x?xf32>) -> tensor<?x?xf32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%arg2 : tensor<?x?xf32>) {
@@ -181,20 +155,7 @@ func.func @specialize_powf_float(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>,
// CHECK-LABEL: specialize_powf_float
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xf32>, %[[ARG1:.+]]: tensor<?x?xf32>, %[[ARG2:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.powf ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
-
-func.func @specialize_add_complex(%arg0: tensor<?x?xcomplex<f32>>, %arg1: tensor<?x?xcomplex<f32>>, %arg2: tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>> {
- %0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%arg2 : tensor<?x?xcomplex<f32>>) {
- ^bb0(%in: complex<f32>, %in_0: complex<f32>, %out: complex<f32>):
- %1 = complex.add %in, %in_0 : complex<f32>
- linalg.yield %1 : complex<f32>
- } -> tensor<?x?xcomplex<f32>>
- return %0 : tensor<?x?xcomplex<f32>>
-}
-// CHECK-LABEL: specialize_add_complex
-// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xcomplex<f32>>, %[[ARG1:.+]]: tensor<?x?xcomplex<f32>>, %[[ARG2:.+]]: tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
-// CHECK-NOT: linalg.generic
-// CHECK: linalg.add ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%[[ARG2]] : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<powf> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
func.func @specialize_sub_complex(%arg0: tensor<?x?xcomplex<f32>>, %arg1: tensor<?x?xcomplex<f32>>, %arg2: tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%arg2 : tensor<?x?xcomplex<f32>>) {
@@ -207,7 +168,7 @@ func.func @specialize_sub_complex(%arg0: tensor<?x?xcomplex<f32>>, %arg1: tensor
// CHECK-LABEL: specialize_sub_complex
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xcomplex<f32>>, %[[ARG1:.+]]: tensor<?x?xcomplex<f32>>, %[[ARG2:.+]]: tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.sub ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%[[ARG2]] : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<sub> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%[[ARG2]] : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
func.func @specialize_mul_complex(%arg0: tensor<?x?xcomplex<f32>>, %arg1: tensor<?x?xcomplex<f32>>, %arg2: tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%arg2 : tensor<?x?xcomplex<f32>>) {
@@ -220,7 +181,7 @@ func.func @specialize_mul_complex(%arg0: tensor<?x?xcomplex<f32>>, %arg1: tensor
// CHECK-LABEL: specialize_mul_complex
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xcomplex<f32>>, %[[ARG1:.+]]: tensor<?x?xcomplex<f32>>, %[[ARG2:.+]]: tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.mul ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%[[ARG2]] : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<mul> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%[[ARG2]] : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
func.func @specialize_div_complex(%arg0: tensor<?x?xcomplex<f32>>, %arg1: tensor<?x?xcomplex<f32>>, %arg2: tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%arg2 : tensor<?x?xcomplex<f32>>) {
@@ -233,20 +194,7 @@ func.func @specialize_div_complex(%arg0: tensor<?x?xcomplex<f32>>, %arg1: tensor
// CHECK-LABEL: specialize_div_complex
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xcomplex<f32>>, %[[ARG1:.+]]: tensor<?x?xcomplex<f32>>, %[[ARG2:.+]]: tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.div ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%[[ARG2]] : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
-
-func.func @specialize_add_bool(%arg0: tensor<?x?xi1>, %arg1: tensor<?x?xi1>, %arg2: tensor<?x?xi1>) -> tensor<?x?xi1> {
- %0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xi1>, tensor<?x?xi1>) outs(%arg2 : tensor<?x?xi1>) {
- ^bb0(%in: i1, %in_0: i1, %out: i1):
- %1 = arith.ori %in, %in_0 : i1
- linalg.yield %1 : i1
- } -> tensor<?x?xi1>
- return %0 : tensor<?x?xi1>
-}
-// CHECK-LABEL: specialize_add_bool
-// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xi1>, %[[ARG1:.+]]: tensor<?x?xi1>, %[[ARG2:.+]]: tensor<?x?xi1>) -> tensor<?x?xi1>
-// CHECK-NOT: linalg.generic
-// CHECK: linalg.add ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi1>, tensor<?x?xi1>) outs(%[[ARG2]] : tensor<?x?xi1>) -> tensor<?x?xi1>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<div> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xcomplex<f32>>, tensor<?x?xcomplex<f32>>) outs(%[[ARG2]] : tensor<?x?xcomplex<f32>>) -> tensor<?x?xcomplex<f32>>
func.func @specialize_mul_bool(%arg0: tensor<?x?xi1>, %arg1: tensor<?x?xi1>, %arg2: tensor<?x?xi1>) -> tensor<?x?xi1> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xi1>, tensor<?x?xi1>) outs(%arg2 : tensor<?x?xi1>) {
@@ -259,7 +207,7 @@ func.func @specialize_mul_bool(%arg0: tensor<?x?xi1>, %arg1: tensor<?x?xi1>, %ar
// CHECK-LABEL: specialize_mul_bool
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xi1>, %[[ARG1:.+]]: tensor<?x?xi1>, %[[ARG2:.+]]: tensor<?x?xi1>) -> tensor<?x?xi1>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.mul ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi1>, tensor<?x?xi1>) outs(%[[ARG2]] : tensor<?x?xi1>) -> tensor<?x?xi1>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<mul> ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xi1>, tensor<?x?xi1>) outs(%[[ARG2]] : tensor<?x?xi1>) -> tensor<?x?xi1>
func.func @specialize_sub_swapped_operands(%arg0: tensor<?x?xf32>, %arg1: tensor<?x?xf32>, %arg2: tensor<?x?xf32>) -> tensor<?x?xf32> {
%0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%arg2 : tensor<?x?xf32>) {
@@ -272,7 +220,7 @@ func.func @specialize_sub_swapped_operands(%arg0: tensor<?x?xf32>, %arg1: tensor
// CHECK-LABEL: specialize_sub_swapped_operands
// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?xf32>, %[[ARG1:.+]]: tensor<?x?xf32>, %[[ARG2:.+]]: tensor<?x?xf32>) -> tensor<?x?xf32>
// CHECK-NOT: linalg.generic
-// CHECK: linalg.sub ins(%[[ARG1]], %[[ARG0]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
+// CHECK: linalg.elementwise kind=#linalg.elementwise_kind<sub> ins(%[[ARG1]], %[[ARG0]] : tensor<?x?xf32>, tensor<?x?xf32>) outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
diff --git a/mlir/test/Dialect/SparseTensor/encoding_with_symbols.mlir b/mlir/test/Dialect/SparseTensor/encoding_with_symbols.mlir
index 2a3c5e8142a6e..83ec42ec80422 100644
--- a/mlir/test/Dialect/SparseTensor/encoding_with_symbols.mlir
+++ b/mlir/test/Dialect/SparseTensor/encoding_with_symbols.mlir
@@ -17,8 +17,8 @@ func.func @tensor_add(%arg0: tensor<8x8xf32, #Sparse>) -> tensor<8x8xf32> {
%result_out = tensor.empty() : tensor<8x8xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloc() alignment = 64 : memref<8x8xf32>
- // CHECK: %[[RES:.*]] = linalg.add ins(%{{.*}}, %{{.*}} : tensor<8x8xf32, #[[$SPARSE_1]]>, tensor<8x8xf32, #[[$SPARSE_1]]>)
- %result = linalg.add
+ // CHECK: %[[RES:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%{{.*}}, %{{.*}} : tensor<8x8xf32, #[[$SPARSE_1]]>, tensor<8x8xf32, #[[$SPARSE_1]]>)
+ %result = linalg.elementwise kind=#linalg.elementwise_kind<add>
ins(%arg0, %arg0 : tensor<8x8xf32, #Sparse>, tensor<8x8xf32, #Sparse>)
outs(%result_out : tensor<8x8xf32>) -> tensor<8x8xf32>
diff --git a/mlir/test/Dialect/SparseTensor/external_after_codegen.mlir b/mlir/test/Dialect/SparseTensor/external_after_codegen.mlir
index b217900c64498..f5934ceb84e4f 100644
--- a/mlir/test/Dialect/SparseTensor/external_after_codegen.mlir
+++ b/mlir/test/Dialect/SparseTensor/external_after_codegen.mlir
@@ -23,7 +23,7 @@ func.func @storage_specifier_passthrough(%arg0: tensor<32x32xf32, #CSR>,
%init = tensor.empty() : tensor<32x32xf32>
%out = linalg.fill ins(%cst : f32) outs(%init : tensor<32x32xf32>)
-> tensor<32x32xf32>
- %3 = linalg.add
+ %3 = linalg.elementwise kind=#linalg.elementwise_kind<add>
ins(%arg0, %arg1 : tensor<32x32xf32, #CSR>, tensor<32x32xf32, #CSR>)
outs(%out : tensor<32x32xf32>) -> tensor<32x32xf32>
return %3 : tensor<32x32xf32>
diff --git a/mlir/test/Dialect/Transform/test-promote-tensors.mlir b/mlir/test/Dialect/Transform/test-promote-tensors.mlir
index 93377ed6d31e4..60876e49628d3 100644
--- a/mlir/test/Dialect/Transform/test-promote-tensors.mlir
+++ b/mlir/test/Dialect/Transform/test-promote-tensors.mlir
@@ -35,15 +35,15 @@ func.func @promote_out(%arg0: tensor<?x42xf32>, %arg1: tensor<?x42xf32>, %arg2:
// CHECK: %[[DIM1:.+]] = tensor.dim %[[ARG2]], %[[C1]]
// CHECK: %[[ALLOC:.+]] = bufferization.alloc_tensor(%[[DIM0]], %[[DIM1]]) <{memory_space = 1 : i64}>
// CHECK-NOT: materialize_in_destination
- // CHECK: linalg.add {{.*}} outs(%[[ALLOC]]
- %0 = linalg.add ins(%arg0, %arg1 : tensor<?x42xf32>, tensor<?x42xf32>)
+ // CHECK: linalg.elementwise {{.*}} outs(%[[ALLOC]]
+ %0 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%arg0, %arg1 : tensor<?x42xf32>, tensor<?x42xf32>)
outs(%arg2 : tensor<?x?xf32>) -> tensor<?x?xf32>
return %0 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%root: !transform.any_op) {
- %la = transform.structured.match ops{["linalg.add"]} in %root
+ %la = transform.structured.match ops{["linalg.elementwise"]} in %root
: (!transform.any_op) -> !transform.any_op
%init = transform.get_operand %la[2]
: (!transform.any_op) -> !transform.any_value
@@ -72,15 +72,15 @@ func.func @promote_in0_out_bufferize(%arg0: tensor<?x42xf32>, %arg1: tensor<42x?
// CHECK: %{{.+}} = memref.dim %{{.+}}, %{{.+}} : memref<?x42xf32, strided<[?, ?], offset: ?>>
// CHECK: %[[ALLOC_IN:.+]] = memref.alloc(%{{.+}}) alignment = 64 : memref<?x42xf32, 1>
// CHECK: memref.copy %[[IN0]], %[[ALLOC_IN]] : memref<?x42xf32, strided<[?, ?], offset: ?>> to memref<?x42xf32, 1>
- // CHECK: linalg.add ins(%[[ALLOC_IN]], %[[IN1]] : memref<?x42xf32, 1>, memref<42x?xf32, strided<[?, ?], offset: ?>>) outs(%[[ALLOC_OUT]] : memref<?x?xf32, 1>)
- %0 = linalg.add ins(%arg0, %arg1: tensor<?x42xf32>, tensor<42x?xf32>)
+ // CHECK: linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%[[ALLOC_IN]], %[[IN1]] : memref<?x42xf32, 1>, memref<42x?xf32, strided<[?, ?], offset: ?>>) outs(%[[ALLOC_OUT]] : memref<?x?xf32, 1>)
+ %0 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%arg0, %arg1: tensor<?x42xf32>, tensor<42x?xf32>)
outs(%arg2: tensor<?x?xf32>) -> tensor<?x?xf32>
return %0 : tensor<?x?xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%root: !transform.any_op) {
- %la = transform.structured.match ops{["linalg.add"]} in %root
+ %la = transform.structured.match ops{["linalg.elementwise"]} in %root
: (!transform.any_op) -> !transform.any_op
%op0 = transform.get_operand %la[0]
: (!transform.any_op) -> !transform.any_value
diff --git a/mlir/test/Interfaces/TilingInterface/query-fusability.mlir b/mlir/test/Interfaces/TilingInterface/query-fusability.mlir
index d7b0528a764bb..fbde870807ce8 100644
--- a/mlir/test/Interfaces/TilingInterface/query-fusability.mlir
+++ b/mlir/test/Interfaces/TilingInterface/query-fusability.mlir
@@ -9,7 +9,7 @@ func.func @fusable_with_matching_offsets(%arg0: tensor<10x20xf32>, %arg1: tensor
%slice1 = tensor.insert_slice %arg1 into %dest[%c0, %c0] [10, 20] [1, 1] : tensor<10x20xf32> into tensor<100x200xf32>
// expected-remark @+1 {{can be fused with producer tensor.insert_slice ops}}
- %result = linalg.add ins(%slice0, %slice1 : tensor<100x200xf32>, tensor<100x200xf32>)
+ %result = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%slice0, %slice1 : tensor<100x200xf32>, tensor<100x200xf32>)
outs(%dest : tensor<100x200xf32>) -> tensor<100x200xf32>
return %result : tensor<100x200xf32>
@@ -17,7 +17,7 @@ func.func @fusable_with_matching_offsets(%arg0: tensor<10x20xf32>, %arg1: tensor
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg: !transform.any_op) {
- %add = transform.structured.match ops{["linalg.add"]} in %arg : (!transform.any_op) -> !transform.any_op
+ %add = transform.structured.match ops{["linalg.elementwise"]} in %arg : (!transform.any_op) -> !transform.any_op
transform.test.query_producer_fusability %add : !transform.any_op
transform.yield
}
@@ -34,7 +34,7 @@ func.func @not_fusable_with_different_offsets(%arg0: tensor<10x20xf32>, %arg1: t
%slice1 = tensor.insert_slice %arg1 into %dest[%c10, %c20] [10, 20] [1, 1] : tensor<10x20xf32> into tensor<100x200xf32>
// expected-remark @+1 {{cannot be fused with producer tensor.insert_slice ops}}
- %result = linalg.add ins(%slice0, %slice1 : tensor<100x200xf32>, tensor<100x200xf32>)
+ %result = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%slice0, %slice1 : tensor<100x200xf32>, tensor<100x200xf32>)
outs(%dest : tensor<100x200xf32>) -> tensor<100x200xf32>
return %result : tensor<100x200xf32>
@@ -42,7 +42,7 @@ func.func @not_fusable_with_different_offsets(%arg0: tensor<10x20xf32>, %arg1: t
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg: !transform.any_op) {
- %add = transform.structured.match ops{["linalg.add"]} in %arg : (!transform.any_op) -> !transform.any_op
+ %add = transform.structured.match ops{["linalg.elementwise"]} in %arg : (!transform.any_op) -> !transform.any_op
transform.test.query_producer_fusability %add : !transform.any_op
transform.yield
}
@@ -52,7 +52,7 @@ module attributes {transform.with_named_sequence} {
func.func @fusable_with_consumer_extract_slice(%arg0: tensor<100x200xf32>, %arg1: tensor<100x200xf32>, %dest: tensor<100x200xf32>) -> tensor<10x20xf32> {
// expected-remark @+1 {{can be fused with consumer tensor.extract_slice op}}
- %add = linalg.add ins(%arg0, %arg1 : tensor<100x200xf32>, tensor<100x200xf32>)
+ %add = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%arg0, %arg1 : tensor<100x200xf32>, tensor<100x200xf32>)
outs(%dest : tensor<100x200xf32>) -> tensor<100x200xf32>
%c0 = arith.constant 0 : index
@@ -63,7 +63,7 @@ func.func @fusable_with_consumer_extract_slice(%arg0: tensor<100x200xf32>, %arg1
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg: !transform.any_op) {
- %add = transform.structured.match ops{["linalg.add"]} in %arg : (!transform.any_op) -> !transform.any_op
+ %add = transform.structured.match ops{["linalg.elementwise"]} in %arg : (!transform.any_op) -> !transform.any_op
transform.test.query_consumer_fusability %add : !transform.any_op
transform.yield
}
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 130c1ae383418..5e733cd4d25eb 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
@@ -19,7 +19,7 @@ module {
}
%in_operand_2 = tensor.empty() : tensor<64xf32>
%out_operand_3 = tensor.empty() : tensor<64xf32>
- %2 = linalg.add ins(%1#1, %in_operand_2 : tensor<64xf32>, tensor<64xf32>) outs(%out_operand_3 : tensor<64xf32>) -> tensor<64xf32>
+ %2 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%1#1, %in_operand_2 : tensor<64xf32>, tensor<64xf32>) outs(%out_operand_3 : tensor<64xf32>) -> tensor<64xf32>
return %2 : tensor<64xf32>
}
}
@@ -50,7 +50,7 @@ module attributes {transform.with_named_sequence} {
// CHECK: %[[INSERT_MAT:.*]] = tensor.insert_slice %[[MAT_OUT]] into %[[FIRST_OUT_ARG]][%[[IV]]] [32] [1]
// CHECK: %[[SLICE_OPERAND2:.*]] = tensor.extract_slice %0[%[[IV]]] [32] [1]
// CHECK: %[[SLICE_OUT:.*]] = tensor.extract_slice %[[ELEM_OUT_ARG]][%[[IV]]] [32] [1]
-// CHECK: %[[ELEM_OUT:.*]] = linalg.add
+// CHECK: %[[ELEM_OUT:.*]] = linalg.elementwise
// CHECK-SAME: ins(%[[MAT_OUT]], %[[SLICE_OPERAND2]] :
// CHECK-SAME: outs(%[[SLICE_OUT]] :
// CHECK: %[[INSERT_ELEM:.*]] = tensor.insert_slice %[[ELEM_OUT]] into %[[ELEM_OUT_ARG]][%[[IV]]] [32] [1]
@@ -76,7 +76,7 @@ module {
}
%in_operand_2 = tensor.empty() : tensor<64x64xf32>
%out_operand_3 = tensor.empty() : tensor<64x64xf32>
- %2 = linalg.add ins(%1#1, %in_operand_2 : tensor<64x64xf32>, tensor<64x64xf32>) outs(%out_operand_3 : tensor<64x64xf32>) -> tensor<64x64xf32>
+ %2 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%1#1, %in_operand_2 : tensor<64x64xf32>, tensor<64x64xf32>) outs(%out_operand_3 : tensor<64x64xf32>) -> tensor<64x64xf32>
return %2 : tensor<64x64xf32>
}
}
@@ -109,7 +109,7 @@ module attributes {transform.with_named_sequence} {
// CHECK-SAME: outs(%[[MAT_OUT_SLICE]] :
// CHECK: %[[SLICE_OPERAND2:.*]] = tensor.extract_slice %[[OUT_INIT]][%[[IV1]], %[[IV2]]] [32, 32] [1, 1]
// CHECK: %[[SLICE_OUT:.*]] = tensor.extract_slice %[[ELEM_OUT_ARG]][%[[IV1]], %[[IV2]]] [32, 32] [1, 1]
-// CHECK: %[[ELEM_OUT:.*]] = linalg.add
+// CHECK: %[[ELEM_OUT:.*]] = linalg.elementwise
// CHECK-SAME: ins(%[[MAT_OUT]], %[[SLICE_OPERAND2]] :
// CHECK-SAME: outs(%[[SLICE_OUT]] :
// CHECK: scf.forall.in_parallel {
@@ -705,11 +705,11 @@ module {
%extracted_slice_1 = tensor.extract_slice %arg4[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
%extracted_slice_2 = tensor.extract_slice %arg0[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
%extracted_slice_3 = tensor.extract_slice %arg1[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
- %3 = linalg.add ins(%extracted_slice_2, %extracted_slice_3 : tensor<64x256xf32>, tensor<64x256xf32>) outs(%extracted_slice_1 : tensor<64x256xf32>) -> tensor<64x256xf32>
+ %3 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%extracted_slice_2, %extracted_slice_3 : tensor<64x256xf32>, tensor<64x256xf32>) outs(%extracted_slice_1 : tensor<64x256xf32>) -> tensor<64x256xf32>
%insert_slice = tensor.insert_slice %3 into %arg4[%arg3, 0] [64, 256] [1, 1] : tensor<64x256xf32> into tensor<256x256xf32>
scf.yield %insert_slice : tensor<256x256xf32>
}
- %4 = linalg.mul ins(%1, %arg2 : tensor<256x256xf32>, tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
+ %4 = linalg.elementwise kind=#linalg.elementwise_kind<mul> ins(%1, %arg2 : tensor<256x256xf32>, 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>
}
@@ -737,7 +737,7 @@ module attributes {transform.with_named_sequence} {
// CHECK: %[[ADD_OUT_SLICE:.*]] = tensor.extract_slice %[[FIRST_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
// CHECK: %[[ADD_INS0_SLICE:.*]] = tensor.extract_slice %[[ARG0]][%[[IV1]], 0] [64, 256] [1, 1]
// CHECK: %[[ADD_INS1_SLICE:.*]] = tensor.extract_slice %[[ARG1]][%[[IV1]], 0] [64, 256] [1, 1]
-// CHECK: %[[TILED_ADD_OUT:.*]] = linalg.add
+// CHECK: %[[TILED_ADD_OUT:.*]] = linalg.elementwise
// CHECK-SAME: ins(%[[ADD_INS0_SLICE]], %[[ADD_INS1_SLICE]] :
// 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]
@@ -747,7 +747,7 @@ module attributes {transform.with_named_sequence} {
// CHECK-SAME: outs(%[[EXP_OUT_SLICE]] :
// CHECK: %[[MUL_INS2_SLICE:.*]] = tensor.extract_slice %[[ARG2]][%[[IV1]], 0] [64, 256] [1, 1]
// CHECK: %[[MUL_OUT_SLICE:.*]] = tensor.extract_slice %[[THIRD_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
-// CHECK: %[[TILED_MUL_OUT:.*]] = linalg.mul
+// CHECK: %[[TILED_MUL_OUT:.*]] = linalg.elementwise
// CHECK-SAME: ins(%[[TILED_ADD_OUT]], %[[MUL_INS2_SLICE]] :
// CHECK-SAME: outs(%[[MUL_OUT_SLICE]] :
// CHECK: %[[INSERT_EXP:.*]] = tensor.insert_slice %[[TILED_EXP_OUT]] into %[[SECOND_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
@@ -769,13 +769,13 @@ module {
%extracted_slice_1 = tensor.extract_slice %arg4[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
%extracted_slice_2 = tensor.extract_slice %arg0[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
%extracted_slice_3 = tensor.extract_slice %arg1[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
- %3 = linalg.add ins(%extracted_slice_2, %extracted_slice_3 : tensor<64x256xf32>, tensor<64x256xf32>) outs(%extracted_slice_1 : tensor<64x256xf32>) -> tensor<64x256xf32>
+ %3 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%extracted_slice_2, %extracted_slice_3 : tensor<64x256xf32>, tensor<64x256xf32>) outs(%extracted_slice_1 : tensor<64x256xf32>) -> tensor<64x256xf32>
%insert_slice = tensor.insert_slice %3 into %arg4[%arg3, 0] [64, 256] [1, 1] : tensor<64x256xf32> into tensor<256x256xf32>
scf.yield %insert_slice : tensor<256x256xf32>
}
%dest1 = tensor.empty() : tensor<258x258xf32>
%4 = tensor.insert_slice %1 into %dest1[0, 0] [256, 256] [1, 1] : tensor<256x256xf32> into tensor<258x258xf32>
- %5 = linalg.mul ins(%1, %arg2 : tensor<256x256xf32>, tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
+ %5 = linalg.elementwise kind=#linalg.elementwise_kind<mul> ins(%1, %arg2 : tensor<256x256xf32>, tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
return %5, %4 : tensor<256x256xf32>, tensor<258x258xf32>
}
}
@@ -793,8 +793,8 @@ module attributes {transform.with_named_sequence} {
}
// CHECK: func.func @no_fuse_only_dps_consumer(
// CHECK: %[[LOOP_RESULT:.*]]:2 = scf.for {{.*}} {
-// CHECK: linalg.add
-// CHECK: linalg.mul
+// CHECK: linalg.elementwise
+// CHECK: linalg.elementwise
// CHECK: scf.yield
// CHECK: }
// CHECK: %[[RES_SLICE:.+]] = tensor.insert_slice
@@ -815,7 +815,7 @@ module {
%extracted_slice = tensor.extract_slice %arg4[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
%extracted_slice_0 = tensor.extract_slice %arg0[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
%extracted_slice_1 = tensor.extract_slice %arg1[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
- %4 = linalg.add ins(%extracted_slice_0, %extracted_slice_1 : tensor<64x256xf32>, tensor<64x256xf32>) outs(%extracted_slice : tensor<64x256xf32>) -> tensor<64x256xf32>
+ %4 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%extracted_slice_0, %extracted_slice_1 : tensor<64x256xf32>, tensor<64x256xf32>) outs(%extracted_slice : tensor<64x256xf32>) -> tensor<64x256xf32>
%inserted_slice = tensor.insert_slice %4 into %arg4[%arg3, 0] [64, 256] [1, 1] : tensor<64x256xf32> into tensor<256x256xf32>
scf.yield %inserted_slice : tensor<256x256xf32>
}
@@ -839,7 +839,7 @@ module {
// CHECK: %[[VAL_12:.*]] = tensor.extract_slice %[[VAL_10]]{{\[}}%[[VAL_9]], 0] [64, 256] [1, 1]
// CHECK: %[[VAL_13:.*]] = tensor.extract_slice %[[VAL_0]]{{\[}}%[[VAL_9]], 0] [64, 256] [1, 1]
// CHECK: %[[VAL_14:.*]] = tensor.extract_slice %[[VAL_1]]{{\[}}%[[VAL_9]], 0] [64, 256] [1, 1]
-// CHECK: %[[VAL_15:.*]] = linalg.add ins(%[[VAL_13]], %[[VAL_14]] : tensor<64x256xf32>, tensor<64x256xf32>) outs(%[[VAL_12]] : tensor<64x256xf32>) -> tensor<64x256xf32>
+// CHECK: %[[VAL_15:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%[[VAL_13]], %[[VAL_14]] : tensor<64x256xf32>, tensor<64x256xf32>) outs(%[[VAL_12]] : tensor<64x256xf32>) -> tensor<64x256xf32>
// CHECK: %[[VAL_16:.*]] = tensor.insert_slice %[[VAL_15]] into %[[VAL_10]]{{\[}}%[[VAL_9]], 0] [64, 256] [1, 1]
// CHECK: %[[VAL_17:.*]] = tensor.extract_slice %[[VAL_2]][0] [24] [1] : tensor<24xf32> to tensor<24xf32>
// CHECK: %[[VAL_18:.*]] = tensor.extract_slice %[[VAL_11]]{{\[}}%[[VAL_9]], 0, 0] [64, 256, 24] [1, 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 f7deb6a05e820..af74ff924524b 100644
--- a/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer.mlir
+++ b/mlir/test/Interfaces/TilingInterface/tile-and-fuse-consumer.mlir
@@ -19,7 +19,7 @@ module {
}
%in_operand_2 = tensor.empty() : tensor<64xf32>
%out_operand_3 = tensor.empty() : tensor<64xf32>
- %2 = linalg.add ins(%1#1, %in_operand_2 : tensor<64xf32>, tensor<64xf32>) outs(%out_operand_3 : tensor<64xf32>) -> tensor<64xf32>
+ %2 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%1#1, %in_operand_2 : tensor<64xf32>, tensor<64xf32>) outs(%out_operand_3 : tensor<64xf32>) -> tensor<64xf32>
return %2 : tensor<64xf32>
}
}
@@ -28,7 +28,7 @@ module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%loop = transform.structured.match ops{["scf.for"]} in %arg1
: (!transform.any_op) -> !transform.any_op
- %add = transform.structured.match ops{["linalg.add"]} in %arg1
+ %add = transform.structured.match ops{["linalg.elementwise"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%a, %new_loop = transform.test.fuse_consumer %add into (%loop)
: (!transform.any_op, !transform.any_op) -> (!transform.any_op, !transform.any_op)
@@ -50,7 +50,7 @@ module attributes {transform.with_named_sequence} {
// CHECK: %[[INSERT_MAT:.*]] = tensor.insert_slice %[[MAT_OUT]] into %[[FIRST_OUT_ARG]][%[[IV]]] [32] [1]
// CHECK: %[[SLICE_OPERAND2:.*]] = tensor.extract_slice %0[%[[IV]]] [32] [1]
// CHECK: %[[SLICE_OUT:.*]] = tensor.extract_slice %[[ELEM_OUT_ARG]][%[[IV]]] [32] [1]
-// CHECK: %[[ELEM_OUT:.*]] = linalg.add
+// CHECK: %[[ELEM_OUT:.*]] = linalg.elementwise
// CHECK-SAME: ins(%[[MAT_OUT]], %[[SLICE_OPERAND2]] :
// CHECK-SAME: outs(%[[SLICE_OUT]] :
// CHECK: %[[INSERT_ELEM:.*]] = tensor.insert_slice %[[ELEM_OUT]] into %[[ELEM_OUT_ARG]][%[[IV]]] [32] [1]
@@ -73,7 +73,7 @@ module {
}
scf.yield %1 : tensor<?x?xf32>
}
- %2 = linalg.add ins(%0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%arg2 : tensor<?x?xf32>) -> tensor<?x?xf32>
+ %2 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>) outs(%arg2 : tensor<?x?xf32>) -> tensor<?x?xf32>
return %2 : tensor<?x?xf32>
}
}
@@ -84,7 +84,7 @@ module attributes {transform.with_named_sequence} {
: (!transform.any_op) -> !transform.any_op
%loop0, %loop1 = transform.split_handle %loops
: (!transform.any_op) -> (!transform.any_op, !transform.any_op)
- %add = transform.structured.match ops{["linalg.add"]} in %arg1
+ %add = transform.structured.match ops{["linalg.elementwise"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%a, %new_loop0, %new_loop1 = transform.test.fuse_consumer %add into (%loop0, %loop1)
: (!transform.any_op, !transform.any_op, !transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
@@ -103,7 +103,7 @@ module attributes {transform.with_named_sequence} {
// CHECK-DAG: %[[OLD_INSERT_SLICE:.+]] = tensor.insert_slice %[[OPERAND1]] into %[[INIT10]]
// CHECK-DAG: %[[OPERAND2:.+]] = tensor.extract_slice %[[ARG1]]
// CHECK-DAG: %[[INIT:.+]] = tensor.extract_slice %[[INIT11]]
-// CHECK: %[[ADD:.+]] = linalg.add
+// CHECK: %[[ADD:.+]] = linalg.elementwise
// CHECK-SAME: ins(%[[OPERAND1]], %[[OPERAND2]] :
// CHECK-SAME: outs(%[[INIT]] :
// CHECK: %[[INSERT_SLICE:.+]] = tensor.insert_slice %[[ADD]] into %[[INIT11]]
@@ -129,14 +129,14 @@ module {
}
%in_operand_2 = tensor.empty() : tensor<64x64xf32>
%out_operand_3 = tensor.empty() : tensor<64x64xf32>
- %2 = linalg.add ins(%1#1, %in_operand_2 : tensor<64x64xf32>, tensor<64x64xf32>) outs(%out_operand_3 : tensor<64x64xf32>) -> tensor<64x64xf32>
+ %2 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%1#1, %in_operand_2 : tensor<64x64xf32>, tensor<64x64xf32>) outs(%out_operand_3 : tensor<64x64xf32>) -> tensor<64x64xf32>
return %2 : tensor<64x64xf32>
}
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
- %add = transform.structured.match ops{["linalg.add"]} in %arg1
+ %add = transform.structured.match ops{["linalg.elementwise"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%loop = transform.structured.match ops{["scf.forall"]} in %arg1
: (!transform.any_op) -> !transform.any_op
@@ -159,7 +159,7 @@ module attributes {transform.with_named_sequence} {
// CHECK-SAME: outs(%[[MAT_OUT_SLICE]] :
// CHECK: %[[SLICE_OPERAND2:.*]] = tensor.extract_slice %[[OUT_INIT]][%[[IV1]], %[[IV2]]] [32, 32] [1, 1]
// CHECK: %[[SLICE_OUT:.*]] = tensor.extract_slice %[[ELEM_OUT_ARG]][%[[IV1]], %[[IV2]]] [32, 32] [1, 1]
-// CHECK: %[[ELEM_OUT:.*]] = linalg.add
+// CHECK: %[[ELEM_OUT:.*]] = linalg.elementwise
// CHECK-SAME: ins(%[[MAT_OUT]], %[[SLICE_OPERAND2]] :
// CHECK-SAME: outs(%[[SLICE_OUT]] :
// CHECK: scf.forall.in_parallel {
@@ -743,11 +743,11 @@ module {
%extracted_slice_1 = tensor.extract_slice %arg4[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
%extracted_slice_2 = tensor.extract_slice %arg0[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
%extracted_slice_3 = tensor.extract_slice %arg1[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
- %3 = linalg.add ins(%extracted_slice_2, %extracted_slice_3 : tensor<64x256xf32>, tensor<64x256xf32>) outs(%extracted_slice_1 : tensor<64x256xf32>) -> tensor<64x256xf32>
+ %3 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%extracted_slice_2, %extracted_slice_3 : tensor<64x256xf32>, tensor<64x256xf32>) outs(%extracted_slice_1 : tensor<64x256xf32>) -> tensor<64x256xf32>
%insert_slice = tensor.insert_slice %3 into %arg4[%arg3, 0] [64, 256] [1, 1] : tensor<64x256xf32> into tensor<256x256xf32>
scf.yield %insert_slice : tensor<256x256xf32>
}
- %4 = linalg.mul ins(%1, %arg2 : tensor<256x256xf32>, tensor<256x256xf32>) outs(%dest0 : tensor<256x256xf32>) -> tensor<256x256xf32>
+ %4 = linalg.elementwise kind=#linalg.elementwise_kind<mul> ins(%1, %arg2 : tensor<256x256xf32>, 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>
}
@@ -755,13 +755,13 @@ module {
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
- %mulop = transform.structured.match ops{["linalg.mul"]} in %arg1
+ %mulop = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<mul>} in %arg1
: (!transform.any_op) -> !transform.any_op
%loop = transform.structured.match ops{["scf.for"]} in %arg1
: (!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.elementwise"]} in %arg1
+ %expop = transform.structured.match ops{["linalg.elementwise"]} attributes{kind = #linalg.elementwise_kind<exp>} 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)
@@ -779,13 +779,13 @@ module attributes {transform.with_named_sequence} {
// CHECK: %[[ADD_OUT_SLICE:.*]] = tensor.extract_slice %[[FIRST_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
// CHECK: %[[ADD_INS0_SLICE:.*]] = tensor.extract_slice %[[ARG0]][%[[IV1]], 0] [64, 256] [1, 1]
// CHECK: %[[ADD_INS1_SLICE:.*]] = tensor.extract_slice %[[ARG1]][%[[IV1]], 0] [64, 256] [1, 1]
-// CHECK: %[[TILED_ADD_OUT:.*]] = linalg.add
+// CHECK: %[[TILED_ADD_OUT:.*]] = linalg.elementwise
// CHECK-SAME: ins(%[[ADD_INS0_SLICE]], %[[ADD_INS1_SLICE]] :
// 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: %[[MUL_INS2_SLICE:.*]] = tensor.extract_slice %[[ARG2]][%[[IV1]], 0] [64, 256] [1, 1]
// CHECK: %[[MUL_OUT_SLICE:.*]] = tensor.extract_slice %[[SECOND_OUT_ARG]][%[[IV1]], 0] [64, 256] [1, 1]
-// CHECK: %[[TILED_MUL_OUT:.*]] = linalg.mul
+// CHECK: %[[TILED_MUL_OUT:.*]] = linalg.elementwise
// 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]
@@ -813,7 +813,7 @@ module {
%extracted_slice = tensor.extract_slice %arg4[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
%extracted_slice_0 = tensor.extract_slice %arg0[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
%extracted_slice_1 = tensor.extract_slice %arg1[%arg3, 0] [64, 256] [1, 1] : tensor<256x256xf32> to tensor<64x256xf32>
- %4 = linalg.add ins(%extracted_slice_0, %extracted_slice_1 : tensor<64x256xf32>, tensor<64x256xf32>) outs(%extracted_slice : tensor<64x256xf32>) -> tensor<64x256xf32>
+ %4 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%extracted_slice_0, %extracted_slice_1 : tensor<64x256xf32>, tensor<64x256xf32>) outs(%extracted_slice : tensor<64x256xf32>) -> tensor<64x256xf32>
%inserted_slice = tensor.insert_slice %4 into %arg4[%arg3, 0] [64, 256] [1, 1] : tensor<64x256xf32> into tensor<256x256xf32>
scf.yield %inserted_slice : tensor<256x256xf32>
}
@@ -849,7 +849,7 @@ module attributes {transform.with_named_sequence} {
// CHECK: %[[VAL_12:.*]] = tensor.extract_slice %[[VAL_10]]{{\[}}%[[VAL_9]], 0] [64, 256] [1, 1]
// CHECK: %[[VAL_13:.*]] = tensor.extract_slice %[[VAL_0]]{{\[}}%[[VAL_9]], 0] [64, 256] [1, 1]
// CHECK: %[[VAL_14:.*]] = tensor.extract_slice %[[VAL_1]]{{\[}}%[[VAL_9]], 0] [64, 256] [1, 1]
-// CHECK: %[[VAL_15:.*]] = linalg.add ins(%[[VAL_13]], %[[VAL_14]] : tensor<64x256xf32>, tensor<64x256xf32>) outs(%[[VAL_12]] : tensor<64x256xf32>) -> tensor<64x256xf32>
+// CHECK: %[[VAL_15:.*]] = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%[[VAL_13]], %[[VAL_14]] : tensor<64x256xf32>, tensor<64x256xf32>) outs(%[[VAL_12]] : tensor<64x256xf32>) -> tensor<64x256xf32>
// CHECK: %[[VAL_16:.*]] = tensor.insert_slice %[[VAL_15]] into %[[VAL_10]]{{\[}}%[[VAL_9]], 0] [64, 256] [1, 1]
// CHECK: %[[VAL_17:.*]] = tensor.extract_slice %[[VAL_2]][0] [24] [1] : tensor<24xf32> to tensor<24xf32>
// CHECK: %[[VAL_18:.*]] = tensor.extract_slice %[[VAL_11]]{{\[}}%[[VAL_9]], 0, 0] [64, 256, 24] [1, 1, 1]
diff --git a/mlir/test/Interfaces/TilingInterface/tile-fuse-and-yield-using-interface.mlir b/mlir/test/Interfaces/TilingInterface/tile-fuse-and-yield-using-interface.mlir
index 3c0ada9d2cabc..a4fe08c0cfe32 100644
--- a/mlir/test/Interfaces/TilingInterface/tile-fuse-and-yield-using-interface.mlir
+++ b/mlir/test/Interfaces/TilingInterface/tile-fuse-and-yield-using-interface.mlir
@@ -80,14 +80,14 @@ func.func @multiple_outputs_fusion_yield_all(%lhs0: tensor<32x32xf32>,
linalg.yield %4, %5: f32, f32
} -> (tensor<32x32xf32>, tensor<32x32xf32>)
- %out3 = linalg.add ins(%out0, %rhs1: tensor<32x32xf32>, tensor<32x32xf32>) outs(%init2: tensor<32x32xf32>) -> tensor<32x32xf32>
+ %out3 = linalg.elementwise kind=#linalg.elementwise_kind<add> ins(%out0, %rhs1: tensor<32x32xf32>, tensor<32x32xf32>) outs(%init2: tensor<32x32xf32>) -> tensor<32x32xf32>
return %out0, %out1, %out3 : tensor<32x32xf32>, tensor<32x32xf32>, tensor<32x32xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg0 : !transform.any_op {transform.readonly}) {
- %add = transform.structured.match ops{["linalg.add"]} in %arg0
+ %add = transform.structured.match ops{["linalg.elementwise"]} in %arg0
: (!transform.any_op) -> !transform.any_op
%a, %b = transform.test.fuse_and_yield %add [16]
: (!transform.any_op) -> (!transform.any_op, !transform.any_op)
@@ -112,7 +112,7 @@ module attributes {transform.with_named_sequence} {
// CHECK-SAME: outs(%[[INIT0_TILE]], %[[INIT1_TILE]] :
// CHECK-DAG: %[[RHS1_TILE:.+]] = tensor.extract_slice %[[RHS1]][%[[IV]], 0]
// CHECK-DAG: %[[INIT2_TILE:.+]] = tensor.extract_slice %[[ITERARG0]][%[[IV]], 0]
-// CHECK: %[[ADD_TILE:.+]] = linalg.add
+// CHECK: %[[ADD_TILE:.+]] = linalg.elementwise
// CHECK-SAME: ins(%[[GENERIC_TILE]]#0, %[[RHS1_TILE]] :
// CHECK-SAME: outs(%[[INIT2_TILE]] :
// CHECK: %[[INSERT0:.+]] = tensor.insert_slice %[[ADD_TILE]] into %[[ITERARG0]][%[[IV]], 0]
More information about the llvm-branch-commits
mailing list