[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