[clang-tools-extra] [clang] [mlir] [llvm] [mlir][TilingInterface] Early return cloned ops if tile sizes are zeros. (PR #75410)
@@ -362,14 +362,21 @@ mlir::scf::tileUsingSCFForOp(RewriterBase &rewriter, TilingInterface op, auto clonedOp = cast( cloneOpAndUpdateDestinationArgs(rewriter, op, clonedOpDestination)); - // 5b. Tile the cloned operation. + // 5b. Early return cloned op if tiling is not happenning. + if (llvm::all_of(tileSizeVector, + [](OpFoldResult v) { return isZeroIndex(v); })) { hanhanW wrote: Really good point! https://github.com/llvm/llvm-project/pull/75410 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [clang-tools-extra] [mlir][TilingInterface] Early return cloned ops if tile sizes are zeros. (PR #75410)
https://github.com/hanhanW updated https://github.com/llvm/llvm-project/pull/75410 >From c07f7e1c5c6f8bbc7189e96096004d39a0a1aa3f Mon Sep 17 00:00:00 2001 From: hanhanW Date: Wed, 13 Dec 2023 15:59:48 -0800 Subject: [PATCH 1/2] [mlir][TilingInterface] Early return cloned ops if tile sizes are zeros. It is a trivial early-return case. If the cloned ops are not returned, it will generate `extract_slice` op that extracts the whole slice. However, it is not folded away. Early-return to avoid the case. E.g., ```mlir func.func @matmul_tensors( %arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { %0 = linalg.matmul ins(%arg0, %arg1: tensor, tensor) outs(%arg2: tensor) -> tensor return %0 : tensor } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { %0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!transform.any_op) -> !transform.any_op %1 = transform.structured.tile_using_for %0 [0, 0, 0] : (!transform.any_op) -> (!transform.any_op) transform.yield } } ``` Apply the transforms and canonicalize the IR: ``` mlir-opt --transform-interpreter -canonicalize input.mlir ``` we will get ```mlir module { func.func @matmul_tensors(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { %c1 = arith.constant 1 : index %c0 = arith.constant 0 : index %dim = tensor.dim %arg0, %c0 : tensor %dim_0 = tensor.dim %arg0, %c1 : tensor %dim_1 = tensor.dim %arg1, %c1 : tensor %extracted_slice = tensor.extract_slice %arg0[0, 0] [%dim, %dim_0] [1, 1] : tensor to tensor %extracted_slice_2 = tensor.extract_slice %arg1[0, 0] [%dim_0, %dim_1] [1, 1] : tensor to tensor %extracted_slice_3 = tensor.extract_slice %arg2[0, 0] [%dim, %dim_1] [1, 1] : tensor to tensor %0 = linalg.matmul ins(%extracted_slice, %extracted_slice_2 : tensor, tensor) outs(%extracted_slice_3 : tensor) -> tensor return %0 : tensor } } ``` --- .../SCF/Transforms/TileUsingInterface.cpp | 11 ++-- mlir/test/Dialect/Linalg/tile-tensors.mlir| 27 +++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp b/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp index 8057b3898012d4..20413aba8730be 100644 --- a/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp @@ -362,14 +362,21 @@ mlir::scf::tileUsingSCFForOp(RewriterBase &rewriter, TilingInterface op, auto clonedOp = cast( cloneOpAndUpdateDestinationArgs(rewriter, op, clonedOpDestination)); - // 5b. Tile the cloned operation. + // 5b. Early return cloned op if tiling is not happenning. + if (llvm::all_of(tileSizeVector, + [](OpFoldResult v) { return isZeroIndex(v); })) { +return scf::SCFTilingResult{/*tiledOps=*/{clonedOp}, /*loops=*/{}, +clonedOp->getResults()}; + } + + // 5c. Tile the cloned operation. FailureOr tiledImplementation = clonedOp.getTiledImplementation(rewriter, offsets, sizes); if (failed(tiledImplementation)) { return rewriter.notifyMatchFailure(op, "failed to tile operation"); } - // 5c. Delete the cloned operation. + // 5d. Delete the cloned operation. rewriter.eraseOp(clonedOp); // If loops are empty, the tiled op is used as the replacement for the untiled diff --git a/mlir/test/Dialect/Linalg/tile-tensors.mlir b/mlir/test/Dialect/Linalg/tile-tensors.mlir index e0429b1f873298..e8e63302286400 100644 --- a/mlir/test/Dialect/Linalg/tile-tensors.mlir +++ b/mlir/test/Dialect/Linalg/tile-tensors.mlir @@ -37,6 +37,33 @@ module attributes {transform.with_named_sequence} { // - +// CHECK-LABEL: func @matmul_tensors_with_size_zeros( +// CHECK-SAME:%[[TA:[0-9a-z]+]]: tensor +// CHECK-SAME:%[[TB:[0-9a-z]+]]: tensor +// CHECK-SAME:%[[TC:[0-9a-z]+]]: tensor) -> tensor { +func.func @matmul_tensors_with_size_zeros( + %arg0: tensor, %arg1: tensor, %arg2: tensor) +-> tensor { + +// CHECK: %[[RES:.*]] = linalg.matmul ins(%[[TA]], %[[TB]] : tensor, tensor) +// CHECK-SAME:outs(%[[TC]] : tensor) -> tensor +// CHECK: return %[[RES]] + %0 = linalg.matmul ins(%arg0, %arg1: tensor, tensor) + outs(%arg2: tensor) +-> tensor + return %0 : tensor +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { +%0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!transform.any_op) -> !transform.any_op +%1 = transform.structured.tile_using_for %0 [0, 0, 0] : (!transform.any_op) -> (!transform.any_op) +transform.yield + } +} + +// - + func.func @generic_op_tensors( %arg0 : tensor, %arg1 : tensor) -> tensor { %c0 = arit
[llvm] [clang] [clang-tools-extra] [mlir] [mlir][TilingInterface] Early return cloned ops if tile sizes are zeros. (PR #75410)
@@ -362,14 +362,20 @@ mlir::scf::tileUsingSCFForOp(RewriterBase &rewriter, TilingInterface op, auto clonedOp = cast( cloneOpAndUpdateDestinationArgs(rewriter, op, clonedOpDestination)); - // 5b. Tile the cloned operation. + // 5b. Early return cloned op if tiling is not happening. hanhanW wrote: I actually tried that, but it crashes about rewriter states. I did not dig into details because I have less experience about that... https://github.com/llvm/llvm-project/pull/75410 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [clang-tools-extra] [mlir] [mlir][TilingInterface] Early return cloned ops if tile sizes are zeros. (PR #75410)
@@ -362,14 +362,20 @@ mlir::scf::tileUsingSCFForOp(RewriterBase &rewriter, TilingInterface op, auto clonedOp = cast( cloneOpAndUpdateDestinationArgs(rewriter, op, clonedOpDestination)); - // 5b. Tile the cloned operation. + // 5b. Early return cloned op if tiling is not happening. hanhanW wrote: My take is that there are issues about replace op with itself. Do you want me to look into the crash further or add more comments to the code and commit? https://github.com/llvm/llvm-project/pull/75410 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [llvm] [mlir] [mlir][TilingInterface] Early return cloned ops if tile sizes are zeros. (PR #75410)
@@ -362,14 +362,20 @@ mlir::scf::tileUsingSCFForOp(RewriterBase &rewriter, TilingInterface op, auto clonedOp = cast( cloneOpAndUpdateDestinationArgs(rewriter, op, clonedOpDestination)); - // 5b. Tile the cloned operation. + // 5b. Early return cloned op if tiling is not happening. hanhanW wrote: I just tested it locally, and think it makes sense to return the cloned op. The suggestion will lead to `rewriter.replace(op, op->getResults())` and get the crash. Returning the cloned op instead of `op` itself or `failure` makes more sense in this case. I will add some comments to it. https://github.com/llvm/llvm-project/pull/75410 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [llvm] [mlir] [mlir][TilingInterface] Early return cloned ops if tile sizes are zeros. (PR #75410)
https://github.com/hanhanW updated https://github.com/llvm/llvm-project/pull/75410 >From c07f7e1c5c6f8bbc7189e96096004d39a0a1aa3f Mon Sep 17 00:00:00 2001 From: hanhanW Date: Wed, 13 Dec 2023 15:59:48 -0800 Subject: [PATCH 1/3] [mlir][TilingInterface] Early return cloned ops if tile sizes are zeros. It is a trivial early-return case. If the cloned ops are not returned, it will generate `extract_slice` op that extracts the whole slice. However, it is not folded away. Early-return to avoid the case. E.g., ```mlir func.func @matmul_tensors( %arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { %0 = linalg.matmul ins(%arg0, %arg1: tensor, tensor) outs(%arg2: tensor) -> tensor return %0 : tensor } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { %0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!transform.any_op) -> !transform.any_op %1 = transform.structured.tile_using_for %0 [0, 0, 0] : (!transform.any_op) -> (!transform.any_op) transform.yield } } ``` Apply the transforms and canonicalize the IR: ``` mlir-opt --transform-interpreter -canonicalize input.mlir ``` we will get ```mlir module { func.func @matmul_tensors(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { %c1 = arith.constant 1 : index %c0 = arith.constant 0 : index %dim = tensor.dim %arg0, %c0 : tensor %dim_0 = tensor.dim %arg0, %c1 : tensor %dim_1 = tensor.dim %arg1, %c1 : tensor %extracted_slice = tensor.extract_slice %arg0[0, 0] [%dim, %dim_0] [1, 1] : tensor to tensor %extracted_slice_2 = tensor.extract_slice %arg1[0, 0] [%dim_0, %dim_1] [1, 1] : tensor to tensor %extracted_slice_3 = tensor.extract_slice %arg2[0, 0] [%dim, %dim_1] [1, 1] : tensor to tensor %0 = linalg.matmul ins(%extracted_slice, %extracted_slice_2 : tensor, tensor) outs(%extracted_slice_3 : tensor) -> tensor return %0 : tensor } } ``` --- .../SCF/Transforms/TileUsingInterface.cpp | 11 ++-- mlir/test/Dialect/Linalg/tile-tensors.mlir| 27 +++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp b/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp index 8057b3898012d4..20413aba8730be 100644 --- a/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp @@ -362,14 +362,21 @@ mlir::scf::tileUsingSCFForOp(RewriterBase &rewriter, TilingInterface op, auto clonedOp = cast( cloneOpAndUpdateDestinationArgs(rewriter, op, clonedOpDestination)); - // 5b. Tile the cloned operation. + // 5b. Early return cloned op if tiling is not happenning. + if (llvm::all_of(tileSizeVector, + [](OpFoldResult v) { return isZeroIndex(v); })) { +return scf::SCFTilingResult{/*tiledOps=*/{clonedOp}, /*loops=*/{}, +clonedOp->getResults()}; + } + + // 5c. Tile the cloned operation. FailureOr tiledImplementation = clonedOp.getTiledImplementation(rewriter, offsets, sizes); if (failed(tiledImplementation)) { return rewriter.notifyMatchFailure(op, "failed to tile operation"); } - // 5c. Delete the cloned operation. + // 5d. Delete the cloned operation. rewriter.eraseOp(clonedOp); // If loops are empty, the tiled op is used as the replacement for the untiled diff --git a/mlir/test/Dialect/Linalg/tile-tensors.mlir b/mlir/test/Dialect/Linalg/tile-tensors.mlir index e0429b1f873298..e8e63302286400 100644 --- a/mlir/test/Dialect/Linalg/tile-tensors.mlir +++ b/mlir/test/Dialect/Linalg/tile-tensors.mlir @@ -37,6 +37,33 @@ module attributes {transform.with_named_sequence} { // - +// CHECK-LABEL: func @matmul_tensors_with_size_zeros( +// CHECK-SAME:%[[TA:[0-9a-z]+]]: tensor +// CHECK-SAME:%[[TB:[0-9a-z]+]]: tensor +// CHECK-SAME:%[[TC:[0-9a-z]+]]: tensor) -> tensor { +func.func @matmul_tensors_with_size_zeros( + %arg0: tensor, %arg1: tensor, %arg2: tensor) +-> tensor { + +// CHECK: %[[RES:.*]] = linalg.matmul ins(%[[TA]], %[[TB]] : tensor, tensor) +// CHECK-SAME:outs(%[[TC]] : tensor) -> tensor +// CHECK: return %[[RES]] + %0 = linalg.matmul ins(%arg0, %arg1: tensor, tensor) + outs(%arg2: tensor) +-> tensor + return %0 : tensor +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { +%0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!transform.any_op) -> !transform.any_op +%1 = transform.structured.tile_using_for %0 [0, 0, 0] : (!transform.any_op) -> (!transform.any_op) +transform.yield + } +} + +// - + func.func @generic_op_tensors( %arg0 : tensor, %arg1 : tensor) -> tensor { %c0 = arit
[mlir] [clang-tools-extra] [llvm] [clang] [mlir][TilingInterface] Early return cloned ops if tile sizes are zeros. (PR #75410)
https://github.com/hanhanW closed https://github.com/llvm/llvm-project/pull/75410 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [libc] [flang] [clang-tools-extra] [mlir] [llvm] [libcxx] [mlir][Linalg] Support dynamic tiles in `lower_pack` transform (PR #76003)
hanhanW wrote: I'm -1 on using `tensor.reshape` op. IMO, we should only use tensor.expand/collapse_shape; they work much better with existing transformations. Out of curiosity, what use case do you have in mind? Why do we lower fully dynamic pack op? If it is at high level graph level, we can just use `tensor.pack` which carries more meaningful information. If it is at low level stage (e.g., around vectorization), I think the inner tile sizes should already be resolved to static values? In this context, we can still use `tensor.expand_shape`. It supports the case where one dynamic extent can be expanded into a single dynamic extent and other static extents (e.g., `? -> ?x4`). https://github.com/llvm/llvm-project/pull/76003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [clang-tools-extra] [compiler-rt] [libc] [libcxx] [llvm] [mlir] [mlir][Linalg] Support dynamic tiles in `lower_pack` transform (PR #76003)
hanhanW wrote: > I am curious though, what do you mean by more powerful expand_shape op? > Wouldn't that just be exactly reshape? We don't need a more powerful > expand_shape to cover all the cases you mention above. That could be tensor.reshape, but I don't see a scenario about using it. To be honest, I don't have an answer. Bailing out the case is fine to me. If someday people think it is needed, this will help bring up the discussion. To be clear, I am not saying that this is not useful. I just don't know why this is needed. https://github.com/llvm/llvm-project/pull/76003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [lldb] [clang-tools-extra] [clang] [libunwind] [libc] [compiler-rt] [flang] [lld] [libclc] [mlir] [libcxx] [mlir][tensor] Enhance pack/unpack simplification for identity outer_dims_perm cases.
https://github.com/hanhanW updated https://github.com/llvm/llvm-project/pull/77409 >From e74b859897cdf1b1effbbd48a4e5376a231f7132 Mon Sep 17 00:00:00 2001 From: hanhanW Date: Mon, 8 Jan 2024 20:17:30 -0800 Subject: [PATCH 1/2] [mlir][tensor] Enhance pack/unpack simplication patterns for identity outer_dims_perm cases. They can be simplified to reshape ops if outer_dims_perm is an identity permutation. The revision adds a `isIdentityPermutation` method to IndexingUtils. --- .../mlir/Dialect/Utils/IndexingUtils.h| 3 +++ .../Dialect/Tensor/Transforms/CMakeLists.txt | 1 + .../Transforms/PackAndUnpackPatterns.cpp | 17 + mlir/lib/Dialect/Utils/IndexingUtils.cpp | 8 +++ .../Dialect/Tensor/simplify-pack-unpack.mlir | 24 +++ 5 files changed, 48 insertions(+), 5 deletions(-) diff --git a/mlir/include/mlir/Dialect/Utils/IndexingUtils.h b/mlir/include/mlir/Dialect/Utils/IndexingUtils.h index f51a8b28b7548e..2453d841f633e4 100644 --- a/mlir/include/mlir/Dialect/Utils/IndexingUtils.h +++ b/mlir/include/mlir/Dialect/Utils/IndexingUtils.h @@ -228,6 +228,9 @@ void applyPermutationToVector(SmallVector &inVec, /// Helper method to apply to inverse a permutation. SmallVector invertPermutationVector(ArrayRef permutation); +/// Returns true if `permutation` is an identity permutation. +bool isIdentityPermutation(ArrayRef permutation); + /// Method to check if an interchange vector is a permutation. bool isPermutationVector(ArrayRef interchange); diff --git a/mlir/lib/Dialect/Tensor/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Tensor/Transforms/CMakeLists.txt index cbc0d499d9d52c..c6ef6ed86e0d9d 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/CMakeLists.txt +++ b/mlir/lib/Dialect/Tensor/Transforms/CMakeLists.txt @@ -27,6 +27,7 @@ add_mlir_dialect_library(MLIRTensorTransforms MLIRArithUtils MLIRBufferizationDialect MLIRBufferizationTransforms + MLIRDialectUtils MLIRIR MLIRLinalgDialect MLIRMemRefDialect diff --git a/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp b/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp index cfd838e85c1b80..2853cb8fe77a3b 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp @@ -9,6 +9,7 @@ #include "mlir/Dialect/Linalg/IR/Linalg.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/Dialect/Tensor/Transforms/Transforms.h" +#include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/IR/PatternMatch.h" #include "llvm/Support/Debug.h" @@ -38,8 +39,12 @@ struct SimplifyPackToExpandShape : public OpRewritePattern { if (packOp.getPaddingValue()) return rewriter.notifyMatchFailure(packOp, "expects no padding value"); -if (!packOp.getOuterDimsPerm().empty()) - return rewriter.notifyMatchFailure(packOp, "expects no outer_dims_perm"); +auto outerDimsPerm = packOp.getOuterDimsPerm(); +if (!outerDimsPerm.empty() && !isIdentityPermutation(outerDimsPerm)) { + return rewriter.notifyMatchFailure( + packOp, + "expects outer_dims_perm is empty or an identity permutation"); +} RankedTensorType sourceType = packOp.getSourceType(); RankedTensorType destType = packOp.getDestType(); @@ -74,9 +79,11 @@ struct SimplifyUnPackToCollapseShape : public OpRewritePattern { LogicalResult matchAndRewrite(UnPackOp unpackOp, PatternRewriter &rewriter) const override { -if (!unpackOp.getOuterDimsPerm().empty()) { - return rewriter.notifyMatchFailure(unpackOp, - "expects no outer_dims_perm"); +auto outerDimsPerm = unpackOp.getOuterDimsPerm(); +if (!outerDimsPerm.empty() && !isIdentityPermutation(outerDimsPerm)) { + return rewriter.notifyMatchFailure( + unpackOp, + "expects outer_dims_perm is empty or an identity permutation"); } RankedTensorType sourceType = unpackOp.getSourceType(); diff --git a/mlir/lib/Dialect/Utils/IndexingUtils.cpp b/mlir/lib/Dialect/Utils/IndexingUtils.cpp index bb8a0d5912d7c1..f3de454dc4b81a 100644 --- a/mlir/lib/Dialect/Utils/IndexingUtils.cpp +++ b/mlir/lib/Dialect/Utils/IndexingUtils.cpp @@ -213,6 +213,14 @@ mlir::invertPermutationVector(ArrayRef permutation) { return inversion; } +bool mlir::isIdentityPermutation(ArrayRef permutation) { + int n = permutation.size(); + for (int i = 0; i < n; ++i) +if (permutation[i] != i) + return false; + return true; +} + bool mlir::isPermutationVector(ArrayRef interchange) { assert(llvm::all_of(interchange, [](int64_t s) { return s >= 0; }) && "permutation must be non-negative"); diff --git a/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir b/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir index b78ab9bb3fd87e..ffbb2278a2e327 100644 --- a/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir +++ b/mlir/test/Dialect/Tenso
[libcxx] [libc] [lld] [clang-tools-extra] [libclc] [lldb] [llvm] [clang] [compiler-rt] [flang] [mlir] [libunwind] [mlir][tensor] Enhance pack/unpack simplification for identity outer_dims_perm cases.
https://github.com/hanhanW closed https://github.com/llvm/llvm-project/pull/77409 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reland "[mlir][arith] Canonicalization patterns for `arith.select` (#67809)" (PR #68941)
https://github.com/hanhanW updated https://github.com/llvm/llvm-project/pull/68941 >From 877111a139b2f01037fdbe7c0cb120a2f4e64562 Mon Sep 17 00:00:00 2001 From: hanhanW Date: Thu, 12 Oct 2023 17:14:29 -0700 Subject: [PATCH 1/2] Reland "[mlir][arith] Canonicalization patterns for `arith.select` (#67809)" This cherry-picks the changes in llvm-project/5bf701a6687a46fd898621f5077959ff202d716b with limiting types to i1. --- .../Dialect/Arith/IR/ArithCanonicalization.td | 46 +++ mlir/lib/Dialect/Arith/IR/ArithOps.cpp| 4 +- mlir/test/Dialect/Arith/canonicalize.mlir | 76 +++ 3 files changed, 125 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td b/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td index f3d84d0b261e8dd..817de0e06c661b9 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td +++ b/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td @@ -233,6 +233,52 @@ def CmpIExtUI : CPred<"$0.getValue() == arith::CmpIPredicate::eq || " "$0.getValue() == arith::CmpIPredicate::ne">> $pred)]>; +//===--===// +// SelectOp +//===--===// + +// select(not(pred), a, b) => select(pred, b, a) +def SelectNotCond : +Pat<(SelectOp (Arith_XOrIOp $pred, (ConstantLikeMatcher APIntAttr:$ones)), $a, $b), +(SelectOp $pred, $b, $a), +[(IsScalarOrSplatNegativeOne $ones)]>; + +// select(pred, select(pred, a, b), c) => select(pred, a, c) +def RedundantSelectTrue : +Pat<(SelectOp $pred, (SelectOp $pred, $a, $b), $c), +(SelectOp $pred, $a, $c)>; + +// select(pred, a, select(pred, b, c)) => select(pred, a, c) +def RedundantSelectFalse : +Pat<(SelectOp $pred, $a, (SelectOp $pred, $b, $c)), +(SelectOp $pred, $a, $c)>; + +// select(predA, select(predB, x, y), y) => select(and(predA, predB), x, y) +def SelectAndCond : +Pat<(SelectOp $predA, (SelectOp $predB, $x, $y), $y), +(SelectOp (Arith_AndIOp $predA, $predB), $x, $y)>; + +// select(predA, select(predB, y, x), y) => select(and(predA, not(predB)), x, y) +def SelectAndNotCond : +Pat<(SelectOp $predA, (SelectOp $predB, $y, $x), $y), +(SelectOp (Arith_AndIOp $predA, +(Arith_XOrIOp $predB, (Arith_ConstantOp ConstantAttr))), + $x, $y), +[(Constraint> $predB)]>; + +// select(predA, x, select(predB, x, y)) => select(or(predA, predB), x, y) +def SelectOrCond : +Pat<(SelectOp $predA, $x, (SelectOp $predB, $x, $y)), +(SelectOp (Arith_OrIOp $predA, $predB), $x, $y)>; + +// select(predA, x, select(predB, y, x)) => select(or(predA, not(predB)), x, y) +def SelectOrNotCond : +Pat<(SelectOp $predA, $x, (SelectOp $predB, $y, $x)), +(SelectOp (Arith_OrIOp $predA, + (Arith_XOrIOp $predB, (Arith_ConstantOp ConstantAttr))), + $x, $y), +[(Constraint> $predB)]>; + //===--===// // IndexCastOp //===--===// diff --git a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp index ae8a6ef350ce191..0ecc288f3b07701 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp +++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp @@ -2212,7 +2212,9 @@ struct SelectToExtUI : public OpRewritePattern { void arith::SelectOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add(context); + results.add(context); } OpFoldResult arith::SelectOp::fold(FoldAdaptor adaptor) { diff --git a/mlir/test/Dialect/Arith/canonicalize.mlir b/mlir/test/Dialect/Arith/canonicalize.mlir index f697f3d01458eee..1b0547c9e8f804a 100644 --- a/mlir/test/Dialect/Arith/canonicalize.mlir +++ b/mlir/test/Dialect/Arith/canonicalize.mlir @@ -128,6 +128,82 @@ func.func @selToArith(%arg0: i1, %arg1 : i1, %arg2 : i1) -> i1 { return %res : i1 } +// CHECK-LABEL: @redundantSelectTrue +// CHECK-NEXT: %[[res:.+]] = arith.select %arg0, %arg1, %arg3 +// CHECK-NEXT: return %[[res]] +func.func @redundantSelectTrue(%arg0: i1, %arg1 : i32, %arg2 : i32, %arg3 : i32) -> i32 { + %0 = arith.select %arg0, %arg1, %arg2 : i32 + %res = arith.select %arg0, %0, %arg3 : i32 + return %res : i32 +} + +// CHECK-LABEL: @redundantSelectFalse +// CHECK-NEXT: %[[res:.+]] = arith.select %arg0, %arg3, %arg2 +// CHECK-NEXT: return %[[res]] +func.func @redundantSelectFalse(%arg0: i1, %arg1 : i32, %arg2 : i32, %arg3 : i32) -> i32 { + %0 = arith.select %arg0, %arg1, %arg2 : i32 + %res = arith.select %arg0, %arg3, %0 : i32 + return %res : i32 +} + +// CHECK-LABEL: @selNotCond +// CHECK-NEXT: %[[res1:.+]] = arith.select %arg0, %arg2, %arg1
[clang] Reland "[mlir][arith] Canonicalization patterns for `arith.select` (#67809)" (PR #68941)
@@ -233,6 +233,52 @@ def CmpIExtUI : CPred<"$0.getValue() == arith::CmpIPredicate::eq || " "$0.getValue() == arith::CmpIPredicate::ne">> $pred)]>; +//===--===// +// SelectOp +//===--===// + +// select(not(pred), a, b) => select(pred, b, a) +def SelectNotCond : +Pat<(SelectOp (Arith_XOrIOp $pred, (ConstantLikeMatcher APIntAttr:$ones)), $a, $b), +(SelectOp $pred, $b, $a), +[(IsScalarOrSplatNegativeOne $ones)]>; + +// select(pred, select(pred, a, b), c) => select(pred, a, c) +def RedundantSelectTrue : +Pat<(SelectOp $pred, (SelectOp $pred, $a, $b), $c), +(SelectOp $pred, $a, $c)>; + +// select(pred, a, select(pred, b, c)) => select(pred, a, c) +def RedundantSelectFalse : +Pat<(SelectOp $pred, $a, (SelectOp $pred, $b, $c)), +(SelectOp $pred, $a, $c)>; + +// select(predA, select(predB, x, y), y) => select(and(predA, predB), x, y) +def SelectAndCond : +Pat<(SelectOp $predA, (SelectOp $predB, $x, $y), $y), +(SelectOp (Arith_AndIOp $predA, $predB), $x, $y)>; + +// select(predA, select(predB, y, x), y) => select(and(predA, not(predB)), x, y) +def SelectAndNotCond : +Pat<(SelectOp $predA, (SelectOp $predB, $y, $x), $y), +(SelectOp (Arith_AndIOp $predA, +(Arith_XOrIOp $predB, (Arith_ConstantOp ConstantAttr))), hanhanW wrote: done https://github.com/llvm/llvm-project/pull/68941 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reland "[mlir][arith] Canonicalization patterns for `arith.select` (#67809)" (PR #68941)
https://github.com/hanhanW edited https://github.com/llvm/llvm-project/pull/68941 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reland "[mlir][arith] Canonicalization patterns for `arith.select` (#67809)" (PR #68941)
hanhanW wrote: thanks for the review! https://github.com/llvm/llvm-project/pull/68941 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reland "[mlir][arith] Canonicalization patterns for `arith.select` (#67809)" (PR #68941)
https://github.com/hanhanW closed https://github.com/llvm/llvm-project/pull/68941 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [NVPTX] Convert vector function nvvm.annotations to attributes (PR #127736)
hanhanW wrote: Thanks for the heads-up! We do have few cases like: ```cpp setMetadataValueI32("maxntidx", workgroupSize[0]); setMetadataValueI32("maxntidy", workgroupSize[1]); setMetadataValueI32("maxntidz", workgroupSize[2]); https://github.com/llvm/llvm-project/pull/127736 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [mlir] [NVPTX] Convert vector function nvvm.annotations to attributes (PR #127736)
hanhanW wrote: > > I think they will become something like: > > ```c++ > > llvmFunc->addFnAttr("nvvm.maxntid", llvm::utostr(workgroupSize[0])); > > llvmFunc->addFnAttr("nvvm.maxntid", llvm::utostr(workgroupSize[1])); > > llvmFunc->addFnAttr("nvvm.maxntid", llvm::utostr(workgroupSize[2])); > > ``` > > Not quite, this would successively overwrite the "nvvm.maxntid" attribute > three times. I think something like this should work: > > ```c++ > std::string maxntid = llvm::formatv("{0},{1},{2}", workgroupSize[0], > workgroupSize[1], workgroupSize[2]); > llvmFunc->addFnAttr("nvvm.maxntid", maxntid) > ``` I see, thanks! https://github.com/llvm/llvm-project/pull/127736 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits