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

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 30 09:26:34 PDT 2026


================
@@ -3725,14 +3766,77 @@ bool VectorCombine::foldShuffleToIdentity(Instruction &I) {
                               &cast<Instruction>(FrontV)->getOperandUse(0));
         continue;
       } else if (auto *BitCast = dyn_cast<BitCastInst>(FrontV)) {
-        // 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.emplace_back(generateInstLaneVectorFromOperand(Item, 0),
-                                &BitCast->getOperandUse(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.emplace_back(generateInstLaneVectorFromOperand(Item, 0),
+                                  &BitCast->getOperandUse(0));
+            continue;
+          }
+          if (DstElts > SrcElts && 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 [V0, L0] = Item[Idx];
+              if (!V0) {
+                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 [VJ, LJ] = Item[Idx + J];
+                if (!VJ || VJ != V0 || LJ != L0 + (int)J) {
+                  Valid = false;
+                  break;
+                }
+              }
+              if (!Valid)
+                break;
+              assert(isa<Instruction>(V0) && "Expected instruction");
+              NItem.push_back(lookThroughShuffles(
+                  cast<Instruction>(V0)->getOperand(0), L0 / R));
+            }
+            if (Valid) {
+              TraversedElCountChangingBitcast = true;
+              Worklist.emplace_back(NItem, &BitCast->getOperandUse(0));
+              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 [V, Lane] : Item) {
+              if (!V) {
+                for (unsigned J = 0; J < R; ++J)
+                  NItem.push_back({nullptr, PoisonMaskElem});
+                continue;
+              }
+              assert(isa<Instruction>(V) && "Expected instruction");
----------------
arsenm wrote:

```suggestion
```

Redundant 

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


More information about the llvm-commits mailing list