llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Amr Hesham (AmrDeveloper)

<details>
<summary>Changes</summary>

This change adds a folder for the VecSplatOp

Issue https://github.com/llvm/llvm-project/issues/136487

---
Full diff: https://github.com/llvm/llvm-project/pull/143771.diff


6 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+2) 
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+12) 
- (modified) clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp (+2-1) 
- (modified) clang/test/CIR/CodeGen/vector-ext.cpp (+40-22) 
- (modified) clang/test/CIR/CodeGen/vector.cpp (+40-22) 
- (added) clang/test/CIR/Transforms/vector-splat-fold.cir (+16) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 634f0dd554c77..ab132ee5feee0 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2307,6 +2307,8 @@ def VecSplatOp : CIR_Op<"vec.splat", [Pure,
   let assemblyFormat = [{
     $value `:` type($value) `,` qualified(type($result)) attr-dict
   }];
+
+  let hasFolder = 1;
 }
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index a6cf0a6b5d75e..65ad7488be7ca 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1697,6 +1697,18 @@ LogicalResult cir::VecTernaryOp::verify() {
   return success();
 }
 
+// VecSplatOp
+OpFoldResult cir::VecSplatOp::fold(FoldAdaptor adaptor) {
+  mlir::Attribute value = adaptor.getValue();
+  if (!mlir::isa_and_nonnull<cir::IntAttr>(value) &&
+      !mlir::isa_and_nonnull<cir::FPAttr>(value))
+    return {};
+
+  SmallVector<mlir::Attribute, 16> elements(getType().getSize(), value);
+  return cir::ConstVectorAttr::get(
+      getType(), mlir::ArrayAttr::get(getContext(), elements));
+}
+
 OpFoldResult cir::VecTernaryOp::fold(FoldAdaptor adaptor) {
   mlir::Attribute cond = adaptor.getCond();
   mlir::Attribute lhs = adaptor.getLhs();
diff --git a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp 
b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
index 29f9942638964..dc9b0a1546c9c 100644
--- a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
@@ -142,7 +142,8 @@ void CIRCanonicalizePass::runOnOperation() {
     // Many operations are here to perform a manual `fold` in
     // applyOpPatternsGreedily.
     if (isa<BrOp, BrCondOp, CastOp, ScopeOp, SwitchOp, SelectOp, UnaryOp,
-            VecExtractOp, VecShuffleOp, VecShuffleDynamicOp, VecTernaryOp>(op))
+            VecExtractOp, VecShuffleOp, VecShuffleDynamicOp, VecSplatOp,
+            VecTernaryOp>(op))
       ops.push_back(op);
   });
 
diff --git a/clang/test/CIR/CodeGen/vector-ext.cpp 
b/clang/test/CIR/CodeGen/vector-ext.cpp
index 965c44c9461a8..55f917e97ca67 100644
--- a/clang/test/CIR/CodeGen/vector-ext.cpp
+++ b/clang/test/CIR/CodeGen/vector-ext.cpp
@@ -1095,65 +1095,83 @@ void foo17() {
 
 void foo18() {
   vi4 a = {1, 2, 3, 4};
-  vi4 shl = a << 3;
+  int sv = 3;
+  vi4 shl = a << sv;
 
   uvi4 b = {1u, 2u, 3u, 4u};
-  uvi4 shr = b >> 3u;
+  unsigned int usv = 3u;
+  uvi4 shr = b >> usv;
 }
 
 // CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>, ["a", init]
+// CIR: %[[SV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["sv", init]
 // CIR: %[[SHL_RES:.*]] = cir.alloca !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>, ["shl", init]
 // CIR: %[[VEC_B:.*]] = cir.alloca !cir.vector<4 x !u32i>, 
!cir.ptr<!cir.vector<4 x !u32i>>, ["b", init]
+// CIR: %[[USV:.*]] = cir.alloca !u32i, !cir.ptr<!u32i>, ["usv", init]
 // CIR: %[[SHR_RES:.*]] = cir.alloca !cir.vector<4 x !u32i>, 
!cir.ptr<!cir.vector<4 x !u32i>>, ["shr", init]
-// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i
-// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i
-// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !s32i
-// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !s32i
-// CIR: %[[VEC_A_VAL:.*]] = cir.vec.create(%[[CONST_1]], %[[CONST_2]], 
%[[CONST_3]], %[[CONST_4]] :
-// CIR-SAME: !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i>
+// CIR: %[[VEC_A_VAL:.*]] = cir.vec.create({{.*}}, {{.*}}, {{.*}}, {{.*}} : 
!s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i>
 // CIR: cir.store{{.*}} %[[VEC_A_VAL]], %[[VEC_A]] : !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[SV_VAL:.*]] = cir.const #cir.int<3> : !s32i
+// CIR: cir.store{{.*}} %[[SV_VAL]], %[[SV]] : !s32i, !cir.ptr<!s32i>
 // CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[VEC_A]] : !cir.ptr<!cir.vector<4 x 
!s32i>>, !cir.vector<4 x !s32i>
-// CIR: %[[SH_AMOUNT:.*]] = cir.const #cir.int<3> : !s32i
-// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[SH_AMOUNT]] : !s32i, 
!cir.vector<4 x !s32i>
+// CIR: %[[TMP_SV:.*]] = cir.load{{.*}} %[[SV]] : !cir.ptr<!s32i>, !s32i
+// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[TMP_SV]] : !s32i, !cir.vector<4 x 
!s32i>
 // CIR: %[[SHL:.*]] = cir.shift(left, %[[TMP_A]] : !cir.vector<4 x !s32i>, 
%[[SPLAT_VEC]] : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>
 // CIR: cir.store{{.*}} %[[SHL]], %[[SHL_RES]] : !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>
-// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !u32i
-// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !u32i
-// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !u32i
-// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !u32i
-// CIR: %[[VEC_B_VAL:.*]] = cir.vec.create(%[[CONST_1]], %[[CONST_2]], 
%[[CONST_3]], %[[CONST_4]] :
-// CIR-SAME: !u32i, !u32i, !u32i, !u32i) : !cir.vector<4 x !u32i>
+// CIR: %[[VEC_B_VAL:.*]] = cir.vec.create({{.*}}, {{.*}}, {{.*}}, {{.*}} : 
!u32i, !u32i, !u32i, !u32i) : !cir.vector<4 x !u32i>
 // CIR: cir.store{{.*}} %[[VEC_B_VAL]], %[[VEC_B]] : !cir.vector<4 x !u32i>, 
!cir.ptr<!cir.vector<4 x !u32i>>
+// CIR: %[[USV_VAL:.*]] = cir.const #cir.int<3> : !u32i
+// CIR: cir.store{{.*}} %[[USV_VAL]], %[[USV]] : !u32i, !cir.ptr<!u32i>
 // CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[VEC_B]] : !cir.ptr<!cir.vector<4 x 
!u32i>>, !cir.vector<4 x !u32i>
-// CIR: %[[SH_AMOUNT:.*]] = cir.const #cir.int<3> : !u32i
-// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[SH_AMOUNT]] : !u32i, 
!cir.vector<4 x !u32i>
+// CIR: %[[TMP_USV:.*]] = cir.load{{.*}} %[[USV]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[TMP_USV]] : !u32i, !cir.vector<4 
x !u32i>
 // CIR: %[[SHR:.*]] = cir.shift(right, %[[TMP_B]] : !cir.vector<4 x !u32i>, 
%[[SPLAT_VEC]] : !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i>
 // CIR: cir.store{{.*}} %[[SHR]], %[[SHR_RES]] : !cir.vector<4 x !u32i>, 
!cir.ptr<!cir.vector<4 x !u32i>>
 
 // LLVM: %[[VEC_A:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[SV:.*]] = alloca i32, i64 1, align 4
 // LLVM: %[[SHL_RES:.*]] = alloca <4 x i32>, i64 1, align 16
 // LLVM: %[[VEC_B:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[USV:.*]] = alloca i32, i64 1, align 4
 // LLVM: %[[SHR_RES:.*]] = alloca <4 x i32>, i64 1, align 16
 // LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_A]], align 16
+// LLVM: store i32 3, ptr %[[SV]], align 4
 // LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[VEC_A]], align 16
-// LLVM: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], splat (i32 3)
+// LLVM: %[[TMP_SV:.*]] = load i32, ptr %[[SV]], align 4
+// LLVM: %[[SI:.*]] = insertelement <4 x i32> poison, i32 %[[TMP_SV]], i64 0
+// LLVM: %[[S_VEC:.*]] = shufflevector <4 x i32> %[[SI]], <4 x i32> poison, <4 
x i32> zeroinitializer
+// LLVM: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], %[[S_VEC]]
 // LLVM: store <4 x i32> %[[SHL]], ptr %[[SHL_RES]], align 16
 // LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_B]], align 16
+// LLVM: store i32 3, ptr %[[USV]], align 4
 // LLVM: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[VEC_B]], align 16
-// LLVM: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], splat (i32 3)
+// LLVM: %[[TMP_USV:.*]] = load i32, ptr %[[USV]], align 4
+// LLVM: %[[USI:.*]] = insertelement <4 x i32> poison, i32 %[[TMP_USV]], i64 0
+// LLVM: %[[US_VEC:.*]] = shufflevector <4 x i32> %[[USI]], <4 x i32> poison, 
<4 x i32> zeroinitializer
+// LLVM: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], %[[US_VEC]]
 // LLVM: store <4 x i32> %[[SHR]], ptr %[[SHR_RES]], align 16
 
 // OGCG: %[[VEC_A:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[SV:.*]] = alloca i32, align 4
 // OGCG: %[[SHL_RES:.*]] = alloca <4 x i32>, align 16
 // OGCG: %[[VEC_B:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[USV:.*]] = alloca i32, align 4
 // OGCG: %[[SHR_RES:.*]] = alloca <4 x i32>, align 16
 // OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_A]], align 16
+// OGCG: store i32 3, ptr %[[SV]], align 4
 // OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[VEC_A]], align 16
-// OGCG: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], splat (i32 3)
+// OGCG: %[[TMP_SV:.*]] = load i32, ptr %[[SV]], align 4
+// OGCG: %[[SI:.*]] = insertelement <4 x i32> poison, i32 %[[TMP_SV]], i64 0
+// OGCG: %[[S_VEC:.*]] = shufflevector <4 x i32> %[[SI]], <4 x i32> poison, <4 
x i32> zeroinitializer
+// OGCG: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], %[[S_VEC]]
 // OGCG: store <4 x i32> %[[SHL]], ptr %[[SHL_RES]], align 16
 // OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_B]], align 16
+// OGCG: store i32 3, ptr %[[USV]], align 4
 // OGCG: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[VEC_B]], align 16
-// OGCG: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], splat (i32 3)
+// OGCG: %[[TMP_USV:.*]] = load i32, ptr %[[USV]], align 4
+// OGCG: %[[USI:.*]] = insertelement <4 x i32> poison, i32 %[[TMP_USV]], i64 0
+// OGCG: %[[US_VEC:.*]] = shufflevector <4 x i32> %[[USI]], <4 x i32> poison, 
<4 x i32> zeroinitializer
+// OGCG: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], %[[US_VEC]]
 // OGCG: store <4 x i32> %[[SHR]], ptr %[[SHR_RES]], align 16
 
 void foo19() {
diff --git a/clang/test/CIR/CodeGen/vector.cpp 
b/clang/test/CIR/CodeGen/vector.cpp
index 23e91724dc0f3..dfb0078148cbe 100644
--- a/clang/test/CIR/CodeGen/vector.cpp
+++ b/clang/test/CIR/CodeGen/vector.cpp
@@ -1073,65 +1073,83 @@ void foo17() {
 
 void foo18() {
   vi4 a = {1, 2, 3, 4};
-  vi4 shl = a << 3;
+  int sv = 3;
+  vi4 shl = a << sv;
 
   uvi4 b = {1u, 2u, 3u, 4u};
-  uvi4 shr = b >> 3u;
+  unsigned int usv = 3u;
+  uvi4 shr = b >> usv;
 }
 
 // CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>, ["a", init]
+// CIR: %[[SV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["sv", init]
 // CIR: %[[SHL_RES:.*]] = cir.alloca !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>, ["shl", init]
 // CIR: %[[VEC_B:.*]] = cir.alloca !cir.vector<4 x !u32i>, 
!cir.ptr<!cir.vector<4 x !u32i>>, ["b", init]
+// CIR: %[[USV:.*]] = cir.alloca !u32i, !cir.ptr<!u32i>, ["usv", init]
 // CIR: %[[SHR_RES:.*]] = cir.alloca !cir.vector<4 x !u32i>, 
!cir.ptr<!cir.vector<4 x !u32i>>, ["shr", init]
-// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i
-// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i
-// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !s32i
-// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !s32i
-// CIR: %[[VEC_A_VAL:.*]] = cir.vec.create(%[[CONST_1]], %[[CONST_2]], 
%[[CONST_3]], %[[CONST_4]] :
-// CIR-SAME: !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i>
+// CIR: %[[VEC_A_VAL:.*]] = cir.vec.create({{.*}}, {{.*}}, {{.*}}, {{.*}} : 
!s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i>
 // CIR: cir.store{{.*}} %[[VEC_A_VAL]], %[[VEC_A]] : !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[SV_VAL:.*]] = cir.const #cir.int<3> : !s32i
+// CIR: cir.store{{.*}} %[[SV_VAL]], %[[SV]] : !s32i, !cir.ptr<!s32i>
 // CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[VEC_A]] : !cir.ptr<!cir.vector<4 x 
!s32i>>, !cir.vector<4 x !s32i>
-// CIR: %[[SH_AMOUNT:.*]] = cir.const #cir.int<3> : !s32i
-// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[SH_AMOUNT]] : !s32i, 
!cir.vector<4 x !s32i>
+// CIR: %[[TMP_SV:.*]] = cir.load{{.*}} %[[SV]] : !cir.ptr<!s32i>, !s32i
+// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[TMP_SV]] : !s32i, !cir.vector<4 x 
!s32i>
 // CIR: %[[SHL:.*]] = cir.shift(left, %[[TMP_A]] : !cir.vector<4 x !s32i>, 
%[[SPLAT_VEC]] : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>
 // CIR: cir.store{{.*}} %[[SHL]], %[[SHL_RES]] : !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>
-// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !u32i
-// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !u32i
-// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !u32i
-// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !u32i
-// CIR: %[[VEC_B_VAL:.*]] = cir.vec.create(%[[CONST_1]], %[[CONST_2]], 
%[[CONST_3]], %[[CONST_4]] :
-// CIR-SAME: !u32i, !u32i, !u32i, !u32i) : !cir.vector<4 x !u32i>
+// CIR: %[[VEC_B_VAL:.*]] = cir.vec.create({{.*}}, {{.*}}, {{.*}}, {{.*}} : 
!u32i, !u32i, !u32i, !u32i) : !cir.vector<4 x !u32i>
 // CIR: cir.store{{.*}} %[[VEC_B_VAL]], %[[VEC_B]] : !cir.vector<4 x !u32i>, 
!cir.ptr<!cir.vector<4 x !u32i>>
+// CIR: %[[USV_VAL:.*]] = cir.const #cir.int<3> : !u32i
+// CIR: cir.store{{.*}} %[[USV_VAL]], %[[USV]] : !u32i, !cir.ptr<!u32i>
 // CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[VEC_B]] : !cir.ptr<!cir.vector<4 x 
!u32i>>, !cir.vector<4 x !u32i>
-// CIR: %[[SH_AMOUNT:.*]] = cir.const #cir.int<3> : !u32i
-// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[SH_AMOUNT]] : !u32i, 
!cir.vector<4 x !u32i>
+// CIR: %[[TMP_USV:.*]] = cir.load{{.*}} %[[USV]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[TMP_USV]] : !u32i, !cir.vector<4 
x !u32i>
 // CIR: %[[SHR:.*]] = cir.shift(right, %[[TMP_B]] : !cir.vector<4 x !u32i>, 
%[[SPLAT_VEC]] : !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i>
 // CIR: cir.store{{.*}} %[[SHR]], %[[SHR_RES]] : !cir.vector<4 x !u32i>, 
!cir.ptr<!cir.vector<4 x !u32i>>
 
 // LLVM: %[[VEC_A:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[SV:.*]] = alloca i32, i64 1, align 4
 // LLVM: %[[SHL_RES:.*]] = alloca <4 x i32>, i64 1, align 16
 // LLVM: %[[VEC_B:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[USV:.*]] = alloca i32, i64 1, align 4
 // LLVM: %[[SHR_RES:.*]] = alloca <4 x i32>, i64 1, align 16
 // LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_A]], align 16
+// LLVM: store i32 3, ptr %[[SV]], align 4
 // LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[VEC_A]], align 16
-// LLVM: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], splat (i32 3)
+// LLVM: %[[TMP_SV:.*]] = load i32, ptr %[[SV]], align 4
+// LLVM: %[[SI:.*]] = insertelement <4 x i32> poison, i32 %[[TMP_SV]], i64 0
+// LLVM: %[[S_VEC:.*]] = shufflevector <4 x i32> %[[SI]], <4 x i32> poison, <4 
x i32> zeroinitializer
+// LLVM: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], %[[S_VEC]]
 // LLVM: store <4 x i32> %[[SHL]], ptr %[[SHL_RES]], align 16
 // LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_B]], align 16
+// LLVM: store i32 3, ptr %[[USV]], align 4
 // LLVM: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[VEC_B]], align 16
-// LLVM: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], splat (i32 3)
+// LLVM: %[[TMP_USV:.*]] = load i32, ptr %[[USV]], align 4
+// LLVM: %[[USI:.*]] = insertelement <4 x i32> poison, i32 %[[TMP_USV]], i64 0
+// LLVM: %[[US_VEC:.*]] = shufflevector <4 x i32> %[[USI]], <4 x i32> poison, 
<4 x i32> zeroinitializer
+// LLVM: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], %[[US_VEC]]
 // LLVM: store <4 x i32> %[[SHR]], ptr %[[SHR_RES]], align 16
 
 // OGCG: %[[VEC_A:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[SV:.*]] = alloca i32, align 4
 // OGCG: %[[SHL_RES:.*]] = alloca <4 x i32>, align 16
 // OGCG: %[[VEC_B:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[USV:.*]] = alloca i32, align 4
 // OGCG: %[[SHR_RES:.*]] = alloca <4 x i32>, align 16
 // OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_A]], align 16
+// OGCG: store i32 3, ptr %[[SV]], align 4
 // OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[VEC_A]], align 16
-// OGCG: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], splat (i32 3)
+// OGCG: %[[TMP_SV:.*]] = load i32, ptr %[[SV]], align 4
+// OGCG: %[[SI:.*]] = insertelement <4 x i32> poison, i32 %[[TMP_SV]], i64 0
+// OGCG: %[[S_VEC:.*]] = shufflevector <4 x i32> %[[SI]], <4 x i32> poison, <4 
x i32> zeroinitializer
+// OGCG: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], %[[S_VEC]]
 // OGCG: store <4 x i32> %[[SHL]], ptr %[[SHL_RES]], align 16
 // OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_B]], align 16
+// OGCG: store i32 3, ptr %[[USV]], align 4
 // OGCG: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[VEC_B]], align 16
-// OGCG: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], splat (i32 3)
+// OGCG: %[[TMP_USV:.*]] = load i32, ptr %[[USV]], align 4
+// OGCG: %[[USI:.*]] = insertelement <4 x i32> poison, i32 %[[TMP_USV]], i64 0
+// OGCG: %[[US_VEC:.*]] = shufflevector <4 x i32> %[[USI]], <4 x i32> poison, 
<4 x i32> zeroinitializer
+// OGCG: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], %[[US_VEC]]
 // OGCG: store <4 x i32> %[[SHR]], ptr %[[SHR_RES]], align 16
 
 void foo19() {
diff --git a/clang/test/CIR/Transforms/vector-splat-fold.cir 
b/clang/test/CIR/Transforms/vector-splat-fold.cir
new file mode 100644
index 0000000000000..5e3e8ba0eec42
--- /dev/null
+++ b/clang/test/CIR/Transforms/vector-splat-fold.cir
@@ -0,0 +1,16 @@
+// RUN: cir-opt %s -cir-canonicalize -o - | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+
+module  {
+  cir.func @fold_shuffle_vector_op_test() -> !cir.vector<4 x !s32i> {
+    %v = cir.const #cir.int<3> : !s32i
+    %vec = cir.vec.splat %v : !s32i, !cir.vector<4 x !s32i>
+    cir.return %vec : !cir.vector<4 x !s32i>
+  }
+
+  // CHECK: cir.func @fold_shuffle_vector_op_test() -> !cir.vector<4 x !s32i> {
+  // CHECK-NEXT: %0 = cir.const #cir.const_vector<[#cir.int<3> : !s32i, 
#cir.int<3> : !s32i,
+  // CHECK-SAME: #cir.int<3> : !s32i, #cir.int<3> : !s32i]> : !cir.vector<4 x 
!s32i>
+  // CHECK-NEXT: cir.return %0 : !cir.vector<4 x !s32i>
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/143771
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to