[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