[llvm] [InstCombine] Fold `bitcast [x, ..., x] to iN` to `mul x, C` (PR #185907)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 5 10:59:20 PDT 2026
================
@@ -3083,6 +3083,57 @@ static Value *foldCopySignIdioms(BitCastInst &CI,
return Builder.CreateCopySign(Builder.CreateBitCast(Y, FTy), X);
}
+// bitcast (shuf X, Y, splat_mask) to iN --> (zext x) * C
+// where x is the splatted integer source element with bitwidth W and
+// C = 1 + 2^W + 2^(2W) + ... = (2^N - 1)/(2^W - 1)
+// E.g.,
+// x: i1, y = bitcast [x, x, x, x] --> y = x * 15
+// x: i8, y = bitcast [x, x, x, x] --> y = x * 16843009
+static Value *foldSplatShuffleToMul(ShuffleVectorInst *Shuf, IntegerType *DstTy,
+ InstCombiner::BuilderTy &Builder) {
+ auto *ShufTy = dyn_cast<FixedVectorType>(Shuf->getType());
+ if (!ShufTy)
+ return nullptr;
+ auto *EltTy = dyn_cast<IntegerType>(ShufTy->getElementType());
+ // Restrict this fold to integer splats. Reinterpreting a non-integer splat
+ // element as an integer and then multiplying by C is algebraically sound, but
+ // llvm-mca shows that it can generate worse code than keeping the
+ // splat-vector bitcast form.
+ if (!EltTy)
+ return nullptr;
+ ArrayRef<int> Mask = Shuf->getShuffleMask();
+
+ // Check if this is a splat-shuffle with a valid index
+ if (!all_equal(Mask) || Mask[0] == PoisonMaskElem)
+ return nullptr;
+
+ unsigned DstWidth = DstTy->getBitWidth();
+ assert(DstWidth == ShufTy->getPrimitiveSizeInBits().getFixedValue() &&
----------------
dtcxzyw wrote:
It would be less beneficial when the dest type is so large that it needs to be legalized in the backend. Can we be more conservative by checking `DL.fitsInLegalInteger`?
https://github.com/llvm/llvm-project/pull/185907
More information about the llvm-commits
mailing list