[llvm] [SLP]Vectorize single-user instructions as the last-attempt seeds (PR #212579)

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 3 10:48:49 PDT 2026


================
@@ -681,4 +681,58 @@ Intrinsic::ID getMaskedDivRemIntrinsic(unsigned Opcode) {
   }
 }
 
+/// Returns true if \p I is a part of a single-use chain, computing an address,
+/// which does not pay off the vectorization: a constant table is accessed by a
+/// gather, while the indices, unrelated between the lanes, require a full
+/// buildvector, unlike the ones, shifted by a constant from a common base.
+static bool isNonProfitableIndex(const Instruction *I) {
+  constexpr unsigned MaxIndexChainLength = 3;
+  // A constant shift of a common base is a cheap buildvector, while the loads
+  // are vectorized together with the indices, computed from them.
+  auto IsProfitableOperand = [](const Value *V) {
+    if (isa<Constant>(V))
+      return true;
+    if (const auto *Cast = dyn_cast<CastInst>(V); Cast && Cast->hasOneUse())
+      V = Cast->getOperand(0);
+    return isa<LoadInst>(V);
+  };
+  const User *U = I->user_back();
+  for ([[maybe_unused]] unsigned _ : seq<unsigned>(MaxIndexChainLength)) {
+    if (const auto *GEP = dyn_cast<GetElementPtrInst>(U))
+      return isa<Constant>(GEP->getPointerOperand()) ||
+             none_of(I->operand_values(), IsProfitableOperand);
+    if (!isa<Instruction>(U) || !U->hasOneUse())
+      return false;
+    U = U->user_back();
+  }
+  return false;
+}
+
+bool isOnceUsedSeed(const Instruction *I) {
+  if (!I->hasOneUse() || isNonProfitableIndex(I))
+    return false;
+  // The operation with the identity or the absorbing constant is folded away
+  // before the codegen, the vector node only repacks the lanes.
+  if (const auto *BO = dyn_cast<BinaryOperator>(I)) {
+    unsigned Opcode = BO->getOpcode();
+    Type *Ty = BO->getType();
+    for (unsigned Idx : seq<unsigned>(2)) {
+      const auto *C = dyn_cast<Constant>(BO->getOperand(Idx));
+      if (C && (C == ConstantExpr::getBinOpIdentity(
+                         Opcode, Ty, /*AllowRHSConstant=*/Idx == 1) ||
+                C == ConstantExpr::getBinOpAbsorber(
+                         Opcode, Ty, /*AllowLHSConstant=*/Idx == 0)))
+        return false;
+    }
+  }
+  const User *U = I->user_back();
+  if (isa<ExtractElementInst>(I))
----------------
alexey-bataev wrote:

Did not see good examples

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


More information about the llvm-commits mailing list