[llvm] [VectorCombine] Handle widening/narrowing bitcasts in foldShuffleToIdentity (PR #187870)

via llvm-commits llvm-commits at lists.llvm.org
Sat Mar 21 09:25:56 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-vectorizers

Author: AbdallahRashed (AbdallahRashed)

<details>
<summary>Changes</summary>



Track lane indices through vector bitcasts that change element count in foldShuffleToIdentity. Widening bitcasts (e.g. <2 x i32> -> <4 x i16>) compress R consecutive destination lanes into one source lane, while narrowing bitcasts (e.g. <4 x i16> -> <2 x i32>) expand each destination lane into R source lanes.

Also fix identity check, splat mask, and destination type construction to use Item.size() instead of Ty->getNumElements(), since the Item vector changes size when passing through element-count-changing bitcasts.

Fixes #<!-- -->96884.

---

Patch is 30.16 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/187870.diff


5 Files Affected:

- (modified) llvm/lib/Transforms/Vectorize/VectorCombine.cpp (+111-10) 
- (modified) llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll (+71) 
- (modified) llvm/test/Transforms/VectorCombine/X86/shuffle-inseltpoison.ll (+8-16) 
- (modified) llvm/test/Transforms/VectorCombine/X86/shuffle.ll (+8-16) 
- (added) llvm/test/Transforms/VectorCombine/X86/shuffletoidentity-bitcast.ll (+189) 


``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 136f4fe238b34..1144c1d7367ad 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -3521,7 +3521,7 @@ static Value *generateNewInstTree(ArrayRef<InstLane> Item, FixedVectorType *Ty,
     return FrontU->get();
   }
   if (SplatLeafs.contains(FrontU)) {
-    SmallVector<int, 16> Mask(Ty->getNumElements(), FrontLane);
+    SmallVector<int, 16> Mask(Item.size(), FrontLane);
     return Builder.CreateShuffleVector(FrontU->get(), Mask);
   }
   if (ConcatLeafs.contains(FrontU)) {
@@ -3545,6 +3545,51 @@ static Value *generateNewInstTree(ArrayRef<InstLane> Item, FixedVectorType *Ty,
   }
 
   auto *I = cast<Instruction>(FrontU->get());
+
+  // Handle vector bitcasts that change element count. We cannot use
+  // generateInstLaneVectorFromOperand for these because the lane indices
+  // don't map 1:1 through the bitcast.
+  if (auto *BitCast = dyn_cast<BitCastInst>(I)) {
+    auto *BCDstTy = dyn_cast<FixedVectorType>(BitCast->getDestTy());
+    auto *BCSrcTy = dyn_cast<FixedVectorType>(BitCast->getSrcTy());
+    if (BCDstTy && BCSrcTy &&
+        BCDstTy->getNumElements() != BCSrcTy->getNumElements()) {
+      unsigned DstElts = BCDstTy->getNumElements();
+      unsigned SrcElts = BCSrcTy->getNumElements();
+      SmallVector<InstLane> NewItem;
+      if (DstElts > SrcElts) {
+        // Widening: compress operand Item.
+        unsigned R = DstElts / SrcElts;
+        for (unsigned Idx = 0, E = Item.size(); Idx < E; Idx += R) {
+          auto [U, Lane] = Item[Idx];
+          if (!U)
+            NewItem.push_back({nullptr, PoisonMaskElem});
+          else
+            NewItem.push_back(lookThroughShuffles(
+                &cast<Instruction>(U->get())->getOperandUse(0), Lane / R));
+        }
+      } else {
+        // Narrowing: expand operand Item.
+        unsigned R = SrcElts / DstElts;
+        for (auto [U, Lane] : Item) {
+          if (!U) {
+            for (unsigned J = 0; J < R; ++J)
+              NewItem.push_back({nullptr, PoisonMaskElem});
+          } else {
+            for (unsigned J = 0; J < R; ++J)
+              NewItem.push_back(lookThroughShuffles(
+                  &cast<Instruction>(U->get())->getOperandUse(0),
+                  Lane * R + J));
+          }
+        }
+      }
+      Value *Op = generateNewInstTree(NewItem, Ty, IdentityLeafs, SplatLeafs,
+                                      ConcatLeafs, Builder, TTI);
+      return Builder.CreateBitCast(
+          Op, FixedVectorType::get(BCDstTy->getScalarType(), Item.size()));
+    }
+  }
+
   auto *II = dyn_cast<IntrinsicInst>(I);
   unsigned NumOps = I->getNumOperands() - (II ? 1 : 0);
   SmallVector<Value *> Ops(NumOps);
@@ -3565,7 +3610,7 @@ static Value *generateNewInstTree(ArrayRef<InstLane> Item, FixedVectorType *Ty,
       ValueList.push_back(Lane.first->get());
 
   Type *DstTy =
-      FixedVectorType::get(I->getType()->getScalarType(), Ty->getNumElements());
+      FixedVectorType::get(I->getType()->getScalarType(), Item.size());
   if (auto *BI = dyn_cast<BinaryOperator>(I)) {
     auto *Value = Builder.CreateBinOp((Instruction::BinaryOps)BI->getOpcode(),
                                       Ops[0], Ops[1]);
@@ -3636,7 +3681,7 @@ bool VectorCombine::foldShuffleToIdentity(Instruction &I) {
     // Look for an identity value.
     if (FrontLane == 0 &&
         cast<FixedVectorType>(FrontU->get()->getType())->getNumElements() ==
-            Ty->getNumElements() &&
+            Item.size() &&
         all_of(drop_begin(enumerate(Item)), [IsEquiv, Item](const auto &E) {
           Value *FrontV = Item.front().first->get();
           return !E.value().first || (IsEquiv(E.value().first->get(), FrontV) &&
@@ -3714,13 +3759,69 @@ bool VectorCombine::foldShuffleToIdentity(Instruction &I) {
         Worklist.push_back(generateInstLaneVectorFromOperand(Item, 0));
         continue;
       } else if (auto *BitCast = dyn_cast<BitCastInst>(FrontU)) {
-        // TODO: Handle vector widening/narrowing bitcasts.
-        auto *DstTy = dyn_cast<FixedVectorType>(BitCast->getDestTy());
-        auto *SrcTy = dyn_cast<FixedVectorType>(BitCast->getSrcTy());
-        if (DstTy && SrcTy &&
-            SrcTy->getNumElements() == DstTy->getNumElements()) {
-          Worklist.push_back(generateInstLaneVectorFromOperand(Item, 0));
-          continue;
+        auto *BCDstTy = dyn_cast<FixedVectorType>(BitCast->getDestTy());
+        auto *BCSrcTy = dyn_cast<FixedVectorType>(BitCast->getSrcTy());
+        if (BCDstTy && BCSrcTy) {
+          unsigned DstElts = BCDstTy->getNumElements();
+          unsigned SrcElts = BCSrcTy->getNumElements();
+          if (DstElts == SrcElts) {
+            // Same element count - simple pass-through.
+            Worklist.push_back(
+                generateInstLaneVectorFromOperand(Item, 0));
+            continue;
+          }
+          if (DstElts > SrcElts && DstElts % SrcElts == 0 &&
+              Item.size() % (DstElts / SrcElts) == 0) {
+            // Widening bitcast (e.g. <2 x i32> -> <4 x i16>). Compress
+            // consecutive groups of R destination lanes into one source
+            // lane.
+            unsigned R = DstElts / SrcElts;
+            SmallVector<InstLane> NItem;
+            bool Valid = true;
+            for (unsigned Idx = 0, E = Item.size(); Idx < E; Idx += R) {
+              auto [U0, L0] = Item[Idx];
+              if (!U0) {
+                if (any_of(ArrayRef(Item).slice(Idx + 1, R - 1),
+                           [](InstLane IL) { return IL.first != nullptr; }))
+                  { Valid = false; break; }
+                NItem.push_back({nullptr, PoisonMaskElem});
+                continue;
+              }
+              if (L0 % R != 0)
+                { Valid = false; break; }
+              for (unsigned J = 1; J < R; ++J) {
+                auto [UJ, LJ] = Item[Idx + J];
+                if (!UJ || UJ->get() != U0->get() || LJ != L0 + (int)J)
+                  { Valid = false; break; }
+              }
+              if (!Valid) break;
+              NItem.push_back(lookThroughShuffles(
+                  &cast<Instruction>(U0->get())->getOperandUse(0),
+                  L0 / R));
+            }
+            if (Valid) {
+              Worklist.push_back(NItem);
+              continue;
+            }
+          } else if (SrcElts > DstElts && SrcElts % DstElts == 0) {
+            // Narrowing bitcast (e.g. <4 x i16> -> <2 x i32>). Expand
+            // each destination lane into R source lanes.
+            unsigned R = SrcElts / DstElts;
+            SmallVector<InstLane> NItem;
+            for (auto [U, Lane] : Item) {
+              if (!U) {
+                for (unsigned J = 0; J < R; ++J)
+                  NItem.push_back({nullptr, PoisonMaskElem});
+                continue;
+              }
+              for (unsigned J = 0; J < R; ++J)
+                NItem.push_back(lookThroughShuffles(
+                    &cast<Instruction>(U->get())->getOperandUse(0),
+                    Lane * R + J));
+            }
+            Worklist.push_back(NItem);
+            continue;
+          }
         }
       } else if (isa<SelectInst>(FrontU)) {
         Worklist.push_back(generateInstLaneVectorFromOperand(Item, 0));
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
index 7ffd0d29b4f05..e05f1f6ccaa35 100644
--- a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
+++ b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
@@ -1225,3 +1225,74 @@ define <32 x half> @cast_types(<32 x i16> %wide.vec) {
 
 declare <4 x i64> @llvm.fshl.v4i64(<4 x i64>, <4 x i64>, <4 x i64>)
 declare void @use(<4 x i8>)
+
+; Narrowing bitcasts (i16->i32) around a sub, then widening bitcasts (i32->i16)
+; back, split into halves and re-joined. Should fold to a single bitcast+sub+bitcast.
+define <8 x i16> @bitcast_narrowwiden_sub(<8 x i16> %a) {
+; CHECK-LABEL: @bitcast_narrowwiden_sub(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i16> [[A:%.*]] to <4 x i32>
+; CHECK-NEXT:    [[TMP2:%.*]] = sub <4 x i32> zeroinitializer, [[TMP1]]
+; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <4 x i32> [[TMP2]] to <8 x i16>
+; CHECK-NEXT:    ret <8 x i16> [[TMP3]]
+;
+  %lo = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %hi = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+  %bc_lo = bitcast <4 x i16> %lo to <2 x i32>
+  %bc_hi = bitcast <4 x i16> %hi to <2 x i32>
+  %neg_lo = sub <2 x i32> zeroinitializer, %bc_lo
+  %neg_hi = sub <2 x i32> zeroinitializer, %bc_hi
+  %bc_lo2 = bitcast <2 x i32> %neg_lo to <4 x i16>
+  %bc_hi2 = bitcast <2 x i32> %neg_hi to <4 x i16>
+  %result = shufflevector <4 x i16> %bc_lo2, <4 x i16> %bc_hi2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  ret <8 x i16> %result
+}
+
+; Two-operand add through narrowing+widening bitcasts.
+define <8 x i16> @bitcast_narrowwiden_add(<8 x i16> %a, <8 x i16> %b) {
+; CHECK-LABEL: @bitcast_narrowwiden_add(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i16> [[A:%.*]] to <4 x i32>
+; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <8 x i16> [[B:%.*]] to <4 x i32>
+; CHECK-NEXT:    [[TMP3:%.*]] = add <4 x i32> [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <8 x i16>
+; CHECK-NEXT:    ret <8 x i16> [[TMP4]]
+;
+  %a_lo = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %a_hi = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+  %b_lo = shufflevector <8 x i16> %b, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %b_hi = shufflevector <8 x i16> %b, <8 x i16> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+  %bc_a_lo = bitcast <4 x i16> %a_lo to <2 x i32>
+  %bc_a_hi = bitcast <4 x i16> %a_hi to <2 x i32>
+  %bc_b_lo = bitcast <4 x i16> %b_lo to <2 x i32>
+  %bc_b_hi = bitcast <4 x i16> %b_hi to <2 x i32>
+  %add_lo = add <2 x i32> %bc_a_lo, %bc_b_lo
+  %add_hi = add <2 x i32> %bc_a_hi, %bc_b_hi
+  %bc_lo = bitcast <2 x i32> %add_lo to <4 x i16>
+  %bc_hi = bitcast <2 x i32> %add_hi to <4 x i16>
+  %result = shufflevector <4 x i16> %bc_lo, <4 x i16> %bc_hi, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  ret <8 x i16> %result
+}
+
+; Ratio of 4: i8 -> i32 narrowing bitcast with add, then widening back.
+define <16 x i8> @bitcast_narrow4_widen4_add(<16 x i8> %a, <16 x i8> %b) {
+; CHECK-LABEL: @bitcast_narrow4_widen4_add(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <16 x i8> [[A:%.*]] to <4 x i32>
+; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <16 x i8> [[B:%.*]] to <4 x i32>
+; CHECK-NEXT:    [[TMP3:%.*]] = add <4 x i32> [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
+; CHECK-NEXT:    ret <16 x i8> [[TMP4]]
+;
+  %a_lo = shufflevector <16 x i8> %a, <16 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %a_hi = shufflevector <16 x i8> %a, <16 x i8> poison, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  %b_lo = shufflevector <16 x i8> %b, <16 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %b_hi = shufflevector <16 x i8> %b, <16 x i8> poison, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  %bc_a_lo = bitcast <8 x i8> %a_lo to <2 x i32>
+  %bc_a_hi = bitcast <8 x i8> %a_hi to <2 x i32>
+  %bc_b_lo = bitcast <8 x i8> %b_lo to <2 x i32>
+  %bc_b_hi = bitcast <8 x i8> %b_hi to <2 x i32>
+  %add_lo = add <2 x i32> %bc_a_lo, %bc_b_lo
+  %add_hi = add <2 x i32> %bc_a_hi, %bc_b_hi
+  %bc_lo = bitcast <2 x i32> %add_lo to <8 x i8>
+  %bc_hi = bitcast <2 x i32> %add_hi to <8 x i8>
+  %result = shufflevector <8 x i8> %bc_lo, <8 x i8> %bc_hi, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  ret <16 x i8> %result
+}
diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffle-inseltpoison.ll b/llvm/test/Transforms/VectorCombine/X86/shuffle-inseltpoison.ll
index 4c70438b2d6e4..6e099fe22b735 100644
--- a/llvm/test/Transforms/VectorCombine/X86/shuffle-inseltpoison.ll
+++ b/llvm/test/Transforms/VectorCombine/X86/shuffle-inseltpoison.ll
@@ -124,21 +124,17 @@ define <16 x i8> @bitcast_shuf_uses(<4 x i32> %v) {
 define <2 x i64> @PR35454_1(<2 x i64> %v) {
 ; SSE-LABEL: @PR35454_1(
 ; SSE-NEXT:    [[BC:%.*]] = bitcast <2 x i64> [[V:%.*]] to <4 x i32>
-; SSE-NEXT:    [[PERMIL:%.*]] = shufflevector <4 x i32> [[BC]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; SSE-NEXT:    [[BC1:%.*]] = bitcast <4 x i32> [[PERMIL]] to <16 x i8>
+; SSE-NEXT:    [[BC1:%.*]] = bitcast <4 x i32> [[BC]] to <16 x i8>
 ; SSE-NEXT:    [[ADD:%.*]] = shl <16 x i8> [[BC1]], splat (i8 1)
 ; SSE-NEXT:    [[BC2:%.*]] = bitcast <16 x i8> [[ADD]] to <4 x i32>
-; SSE-NEXT:    [[PERMIL1:%.*]] = shufflevector <4 x i32> [[BC2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; SSE-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[PERMIL1]] to <2 x i64>
+; SSE-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[BC2]] to <2 x i64>
 ; SSE-NEXT:    ret <2 x i64> [[BC3]]
 ;
 ; AVX-LABEL: @PR35454_1(
 ; AVX-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> [[V:%.*]] to <16 x i8>
-; AVX-NEXT:    [[BC1:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
-; AVX-NEXT:    [[ADD:%.*]] = shl <16 x i8> [[BC1]], splat (i8 1)
+; AVX-NEXT:    [[ADD:%.*]] = shl <16 x i8> [[TMP1]], splat (i8 1)
 ; AVX-NEXT:    [[BC2:%.*]] = bitcast <16 x i8> [[ADD]] to <4 x i32>
-; AVX-NEXT:    [[PERMIL1:%.*]] = shufflevector <4 x i32> [[BC2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; AVX-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[PERMIL1]] to <2 x i64>
+; AVX-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[BC2]] to <2 x i64>
 ; AVX-NEXT:    ret <2 x i64> [[BC3]]
 ;
   %bc = bitcast <2 x i64> %v to <4 x i32>
@@ -154,21 +150,17 @@ define <2 x i64> @PR35454_1(<2 x i64> %v) {
 define <2 x i64> @PR35454_2(<2 x i64> %v) {
 ; SSE-LABEL: @PR35454_2(
 ; SSE-NEXT:    [[BC:%.*]] = bitcast <2 x i64> [[V:%.*]] to <4 x i32>
-; SSE-NEXT:    [[PERMIL:%.*]] = shufflevector <4 x i32> [[BC]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; SSE-NEXT:    [[BC1:%.*]] = bitcast <4 x i32> [[PERMIL]] to <8 x i16>
+; SSE-NEXT:    [[BC1:%.*]] = bitcast <4 x i32> [[BC]] to <8 x i16>
 ; SSE-NEXT:    [[ADD:%.*]] = shl <8 x i16> [[BC1]], splat (i16 1)
 ; SSE-NEXT:    [[BC2:%.*]] = bitcast <8 x i16> [[ADD]] to <4 x i32>
-; SSE-NEXT:    [[PERMIL1:%.*]] = shufflevector <4 x i32> [[BC2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; SSE-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[PERMIL1]] to <2 x i64>
+; SSE-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[BC2]] to <2 x i64>
 ; SSE-NEXT:    ret <2 x i64> [[BC3]]
 ;
 ; AVX-LABEL: @PR35454_2(
 ; AVX-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> [[V:%.*]] to <8 x i16>
-; AVX-NEXT:    [[BC1:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> <i32 6, i32 7, i32 4, i32 5, i32 2, i32 3, i32 0, i32 1>
-; AVX-NEXT:    [[ADD:%.*]] = shl <8 x i16> [[BC1]], splat (i16 1)
+; AVX-NEXT:    [[ADD:%.*]] = shl <8 x i16> [[TMP1]], splat (i16 1)
 ; AVX-NEXT:    [[BC2:%.*]] = bitcast <8 x i16> [[ADD]] to <4 x i32>
-; AVX-NEXT:    [[PERMIL1:%.*]] = shufflevector <4 x i32> [[BC2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; AVX-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[PERMIL1]] to <2 x i64>
+; AVX-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[BC2]] to <2 x i64>
 ; AVX-NEXT:    ret <2 x i64> [[BC3]]
 ;
   %bc = bitcast <2 x i64> %v to <4 x i32>
diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffle.ll b/llvm/test/Transforms/VectorCombine/X86/shuffle.ll
index 83e088aaa4e27..eccc8cdcc6d91 100644
--- a/llvm/test/Transforms/VectorCombine/X86/shuffle.ll
+++ b/llvm/test/Transforms/VectorCombine/X86/shuffle.ll
@@ -183,22 +183,18 @@ define <2 x i64> @PR35454_1(<2 x i64> %v) {
 ; SSE-LABEL: define <2 x i64> @PR35454_1(
 ; SSE-SAME: <2 x i64> [[V:%.*]]) #[[ATTR0]] {
 ; SSE-NEXT:    [[BC:%.*]] = bitcast <2 x i64> [[V]] to <4 x i32>
-; SSE-NEXT:    [[PERMIL:%.*]] = shufflevector <4 x i32> [[BC]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; SSE-NEXT:    [[BC1:%.*]] = bitcast <4 x i32> [[PERMIL]] to <16 x i8>
+; SSE-NEXT:    [[BC1:%.*]] = bitcast <4 x i32> [[BC]] to <16 x i8>
 ; SSE-NEXT:    [[ADD:%.*]] = shl <16 x i8> [[BC1]], splat (i8 1)
 ; SSE-NEXT:    [[BC2:%.*]] = bitcast <16 x i8> [[ADD]] to <4 x i32>
-; SSE-NEXT:    [[PERMIL1:%.*]] = shufflevector <4 x i32> [[BC2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; SSE-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[PERMIL1]] to <2 x i64>
+; SSE-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[BC2]] to <2 x i64>
 ; SSE-NEXT:    ret <2 x i64> [[BC3]]
 ;
 ; AVX-LABEL: define <2 x i64> @PR35454_1(
 ; AVX-SAME: <2 x i64> [[V:%.*]]) #[[ATTR0]] {
 ; AVX-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> [[V]] to <16 x i8>
-; AVX-NEXT:    [[BC1:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
-; AVX-NEXT:    [[ADD:%.*]] = shl <16 x i8> [[BC1]], splat (i8 1)
+; AVX-NEXT:    [[ADD:%.*]] = shl <16 x i8> [[TMP1]], splat (i8 1)
 ; AVX-NEXT:    [[BC2:%.*]] = bitcast <16 x i8> [[ADD]] to <4 x i32>
-; AVX-NEXT:    [[PERMIL1:%.*]] = shufflevector <4 x i32> [[BC2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; AVX-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[PERMIL1]] to <2 x i64>
+; AVX-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[BC2]] to <2 x i64>
 ; AVX-NEXT:    ret <2 x i64> [[BC3]]
 ;
   %bc = bitcast <2 x i64> %v to <4 x i32>
@@ -215,22 +211,18 @@ define <2 x i64> @PR35454_2(<2 x i64> %v) {
 ; SSE-LABEL: define <2 x i64> @PR35454_2(
 ; SSE-SAME: <2 x i64> [[V:%.*]]) #[[ATTR0]] {
 ; SSE-NEXT:    [[BC:%.*]] = bitcast <2 x i64> [[V]] to <4 x i32>
-; SSE-NEXT:    [[PERMIL:%.*]] = shufflevector <4 x i32> [[BC]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; SSE-NEXT:    [[BC1:%.*]] = bitcast <4 x i32> [[PERMIL]] to <8 x i16>
+; SSE-NEXT:    [[BC1:%.*]] = bitcast <4 x i32> [[BC]] to <8 x i16>
 ; SSE-NEXT:    [[ADD:%.*]] = shl <8 x i16> [[BC1]], splat (i16 1)
 ; SSE-NEXT:    [[BC2:%.*]] = bitcast <8 x i16> [[ADD]] to <4 x i32>
-; SSE-NEXT:    [[PERMIL1:%.*]] = shufflevector <4 x i32> [[BC2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; SSE-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[PERMIL1]] to <2 x i64>
+; SSE-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[BC2]] to <2 x i64>
 ; SSE-NEXT:    ret <2 x i64> [[BC3]]
 ;
 ; AVX-LABEL: define <2 x i64> @PR35454_2(
 ; AVX-SAME: <2 x i64> [[V:%.*]]) #[[ATTR0]] {
 ; AVX-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> [[V]] to <8 x i16>
-; AVX-NEXT:    [[BC1:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> <i32 6, i32 7, i32 4, i32 5, i32 2, i32 3, i32 0, i32 1>
-; AVX-NEXT:    [[ADD:%.*]] = shl <8 x i16> [[BC1]], splat (i16 1)
+; AVX-NEXT:    [[ADD:%.*]] = shl <8 x i16> [[TMP1]], splat (i16 1)
 ; AVX-NEXT:    [[BC2:%.*]] = bitcast <8 x i16> [[ADD]] to <4 x i32>
-; AVX-NEXT:    [[PERMIL1:%.*]] = shufflevector <4 x i32> [[BC2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; AVX-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[PERMIL1]] to <2 x i64>
+; AVX-NEXT:    [[BC3:%.*]] = bitcast <4 x i32> [[BC2]] to <2 x i64>
 ; AVX-NEXT:    ret <2 x i64> [[BC3]]
 ;
   %bc = bitcast <2 x i64> %v to <4 x i32>
diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffletoidentity-bitcast.ll b/llvm/test/Transforms/VectorCombine/X86/shuffletoidentity-bitcast.ll
new file mode 100644
index 0000000000000..34beec2a2fff6
--- /dev/null
+++ b/llvm/test/Transforms/VectorCombine/X86/shuffletoidentity-bitcast.ll
@@ -0,0 +1,189 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=vector-combine -S %s -mtriple=x86_64-- -mattr=+sse2 | FileCheck %s --check-prefixes=CHECK,SSE
+; RUN: opt -passes=vector-combine -S %s -mtriple=x86_64-- -mattr=+avx2 | FileChe...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/187870


More information about the llvm-commits mailing list