https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/143260
>From 14ffd458c4896bd4d5fb73f97c5745db70c8360e Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Sat, 7 Jun 2025 14:43:16 +0200 Subject: [PATCH 1/2] [CIR] Implement folder for VecShuffleOp --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 2 + clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 38 ++++++++++++++++-- .../Dialect/Transforms/CIRCanonicalize.cpp | 2 +- .../CIR/Transforms/vector-shuffle-fold.cir | 39 +++++++++++++++++++ 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 clang/test/CIR/Transforms/vector-shuffle-fold.cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 038a59b8ff4eb..568861cea9f92 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2199,7 +2199,9 @@ def VecShuffleOp : CIR_Op<"vec.shuffle", `(` $vec1 `,` $vec2 `:` qualified(type($vec1)) `)` $indices `:` qualified(type($result)) attr-dict }]; + let hasVerifier = 1; + let hasFolder = 1; } //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index bfd3a0a62a8e7..0eae0494eafd5 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -1580,9 +1580,42 @@ OpFoldResult cir::VecExtractOp::fold(FoldAdaptor adaptor) { } //===----------------------------------------------------------------------===// -// VecShuffle +// VecShuffleOp //===----------------------------------------------------------------------===// +OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) { + mlir::Attribute vec1 = adaptor.getVec1(); + mlir::Attribute vec2 = adaptor.getVec2(); + + if (!mlir::isa_and_nonnull<cir::ConstVectorAttr>(vec1) || + !mlir::isa_and_nonnull<cir::ConstVectorAttr>(vec2)) { + return {}; + } + + auto vec1Attr = mlir::cast<cir::ConstVectorAttr>(vec1); + auto vec2Attr = mlir::cast<cir::ConstVectorAttr>(vec2); + + mlir::ArrayAttr vec1Elts = vec1Attr.getElts(); + mlir::ArrayAttr vec2Elts = vec2Attr.getElts(); + mlir::ArrayAttr indicesElts = adaptor.getIndices(); + + SmallVector<mlir::Attribute, 16> elements; + elements.reserve(indicesElts.size()); + + uint64_t vec1Size = vec1Elts.size(); + for (const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) { + uint64_t idxValue = idxAttr.getUInt(); + if (idxValue < vec1Size) { + elements.push_back(vec1Elts[idxValue]); + } else { + elements.push_back(vec2Elts[idxValue - vec1Size]); + } + } + + return cir::ConstVectorAttr::get( + getType(), mlir::ArrayAttr::get(getContext(), elements)); +} + LogicalResult cir::VecShuffleOp::verify() { // The number of elements in the indices array must match the number of // elements in the result type. @@ -1613,7 +1646,6 @@ OpFoldResult cir::VecShuffleDynamicOp::fold(FoldAdaptor adaptor) { mlir::isa_and_nonnull<cir::ConstVectorAttr>(indices)) { auto vecAttr = mlir::cast<cir::ConstVectorAttr>(vec); auto indicesAttr = mlir::cast<cir::ConstVectorAttr>(indices); - auto vecTy = mlir::cast<cir::VectorType>(vecAttr.getType()); mlir::ArrayAttr vecElts = vecAttr.getElts(); mlir::ArrayAttr indicesElts = indicesAttr.getElts(); @@ -1631,7 +1663,7 @@ OpFoldResult cir::VecShuffleDynamicOp::fold(FoldAdaptor adaptor) { } return cir::ConstVectorAttr::get( - vecTy, mlir::ArrayAttr::get(getContext(), elements)); + getType(), mlir::ArrayAttr::get(getContext(), elements)); } return {}; diff --git a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp index 33881c69eec5f..29f9942638964 100644 --- a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp @@ -142,7 +142,7 @@ void CIRCanonicalizePass::runOnOperation() { // Many operations are here to perform a manual `fold` in // applyOpPatternsGreedily. if (isa<BrOp, BrCondOp, CastOp, ScopeOp, SwitchOp, SelectOp, UnaryOp, - VecExtractOp, VecShuffleDynamicOp, VecTernaryOp>(op)) + VecExtractOp, VecShuffleOp, VecShuffleDynamicOp, VecTernaryOp>(op)) ops.push_back(op); }); diff --git a/clang/test/CIR/Transforms/vector-shuffle-fold.cir b/clang/test/CIR/Transforms/vector-shuffle-fold.cir new file mode 100644 index 0000000000000..a6b43b6f2951d --- /dev/null +++ b/clang/test/CIR/Transforms/vector-shuffle-fold.cir @@ -0,0 +1,39 @@ +// RUN: cir-opt %s -cir-canonicalize -o - -split-input-file | FileCheck %s + +!s32i = !cir.int<s, 32> +!s64i = !cir.int<s, 64> + +module { + cir.func @fold_shuffle_vector_op_test() -> !cir.vector<4 x !s32i> { + %vec_1 = cir.const #cir.const_vector<[#cir.int<1> : !s32i, #cir.int<3> : !s32i, #cir.int<5> : !s32i, #cir.int<7> : !s32i]> : !cir.vector<4 x !s32i> + %vec_2 = cir.const #cir.const_vector<[#cir.int<2> : !s32i, #cir.int<4> : !s32i, #cir.int<6> : !s32i, #cir.int<8> : !s32i]> : !cir.vector<4 x !s32i> + %new_vec = cir.vec.shuffle(%vec_1, %vec_2 : !cir.vector<4 x !s32i>) [#cir.int<0> : !s64i, #cir.int<4> : !s64i, + #cir.int<1> : !s64i, #cir.int<5> : !s64i] : !cir.vector<4 x !s32i> + cir.return %new_vec : !cir.vector<4 x !s32i> + } + + // CHECK: cir.func @fold_shuffle_vector_op_test() -> !cir.vector<4 x !s32i> { + // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i, + // CHECK-SAME: #cir.int<4> : !s32i]> : !cir.vector<4 x !s32i> + // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s32i> +} + +// ----- + +!s32i = !cir.int<s, 32> +!s64i = !cir.int<s, 64> + +module { + cir.func @fold_shuffle_vector_op_test() -> !cir.vector<6 x !s32i> { + %vec_1 = cir.const #cir.const_vector<[#cir.int<1> : !s32i, #cir.int<3> : !s32i, #cir.int<5> : !s32i, #cir.int<7> : !s32i]> : !cir.vector<4 x !s32i> + %vec_2 = cir.const #cir.const_vector<[#cir.int<2> : !s32i, #cir.int<4> : !s32i, #cir.int<6> : !s32i, #cir.int<8> : !s32i]> : !cir.vector<4 x !s32i> + %new_vec = cir.vec.shuffle(%vec_1, %vec_2 : !cir.vector<4 x !s32i>) [#cir.int<0> : !s64i, #cir.int<4> : !s64i, + #cir.int<1> : !s64i, #cir.int<5> : !s64i, #cir.int<2> : !s64i, #cir.int<6> : !s64i] : !cir.vector<6 x !s32i> + cir.return %new_vec : !cir.vector<6 x !s32i> + } + + // CHECK: cir.func @fold_shuffle_vector_op_test() -> !cir.vector<6 x !s32i> { + // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i, + // CHECK-SAME: #cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i]> : !cir.vector<6 x !s32i> + // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<6 x !s32i> +} >From f9fad4a97e861bc76e2b9846c685b0e72e031e0d Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Sun, 8 Jun 2025 12:38:26 +0200 Subject: [PATCH 2/2] Add support for -1 index in the folder --- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 7 +++++++ .../CIR/Transforms/vector-shuffle-fold.cir | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 0eae0494eafd5..a42cba7d6e159 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -1594,6 +1594,8 @@ OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) { auto vec1Attr = mlir::cast<cir::ConstVectorAttr>(vec1); auto vec2Attr = mlir::cast<cir::ConstVectorAttr>(vec2); + mlir::Type vec1ElemTy = + mlir::cast<cir::VectorType>(vec1Attr.getType()).getElementType(); mlir::ArrayAttr vec1Elts = vec1Attr.getElts(); mlir::ArrayAttr vec2Elts = vec2Attr.getElts(); @@ -1604,6 +1606,11 @@ OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) { uint64_t vec1Size = vec1Elts.size(); for (const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) { + if (idxAttr.getSInt() == -1) { + elements.push_back(cir::UndefAttr::get(vec1ElemTy)); + continue; + } + uint64_t idxValue = idxAttr.getUInt(); if (idxValue < vec1Size) { elements.push_back(vec1Elts[idxValue]); diff --git a/clang/test/CIR/Transforms/vector-shuffle-fold.cir b/clang/test/CIR/Transforms/vector-shuffle-fold.cir index a6b43b6f2951d..5a64b938d71c2 100644 --- a/clang/test/CIR/Transforms/vector-shuffle-fold.cir +++ b/clang/test/CIR/Transforms/vector-shuffle-fold.cir @@ -37,3 +37,23 @@ module { // CHECK-SAME: #cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i]> : !cir.vector<6 x !s32i> // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<6 x !s32i> } + +// ----- + +!s32i = !cir.int<s, 32> +!s64i = !cir.int<s, 64> + +module { + cir.func @fold_shuffle_vector_op_test() -> !cir.vector<4 x !s32i> { + %vec_1 = cir.const #cir.const_vector<[#cir.int<1> : !s32i, #cir.int<3> : !s32i, #cir.int<5> : !s32i, #cir.int<7> : !s32i]> : !cir.vector<4 x !s32i> + %vec_2 = cir.const #cir.const_vector<[#cir.int<2> : !s32i, #cir.int<4> : !s32i, #cir.int<6> : !s32i, #cir.int<8> : !s32i]> : !cir.vector<4 x !s32i> + %new_vec = cir.vec.shuffle(%vec_1, %vec_2 : !cir.vector<4 x !s32i>) [#cir.int<-1> : !s64i, #cir.int<4> : !s64i, + #cir.int<1> : !s64i, #cir.int<5> : !s64i] : !cir.vector<4 x !s32i> + cir.return %new_vec : !cir.vector<4 x !s32i> + } + + // CHECK: cir.func @fold_shuffle_vector_op_test() -> !cir.vector<6 x !s32i> { + // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.undef : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i, + // CHECK-SAME: #cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i]> : !cir.vector<6 x !s32i> + // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<6 x !s32i> +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits