[llvm] [InstCombine] Fold variable extract of a constant-strided pointer vector (PR #217078)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 19 09:05:20 PDT 2026
================
@@ -410,6 +410,83 @@ static ConstantInt *getPreferredVectorIndex(ConstantInt *IndexC) {
IndexC->getValue().zextOrTrunc(64));
}
+/// Fold a variable extract from a vector of pointers that all point into the
+/// same object at a constant stride
+static Value *
+foldExtractOfStridedPointerVector(ExtractElementInst &EI,
+ InstCombiner::BuilderTy &Builder,
+ const DataLayout &DL) {
+ auto *VecTy = dyn_cast<FixedVectorType>(EI.getVectorOperandType());
+ if (!VecTy || !VecTy->getElementType()->isPointerTy())
+ return nullptr;
+
+ unsigned NumElts = VecTy->getNumElements();
+ if (NumElts < 2)
+ return nullptr;
+
+ // Walk the insertelement chain outermost-first, so the first value seen for
+ // an index is the one that survives
+ SmallVector<Value *> Elts(NumElts, nullptr);
+ unsigned NumFound = 0;
+ for (Value *V = EI.getVectorOperand(); NumFound != NumElts;) {
+ auto *IE = dyn_cast<InsertElementInst>(V);
+ if (!IE)
+ return nullptr;
+ auto *IdxC = dyn_cast<ConstantInt>(IE->getOperand(2));
+ if (!IdxC || IdxC->uge(NumElts))
+ return nullptr;
+ unsigned Idx = IdxC->getZExtValue();
+ if (!Elts[Idx]) {
+ Elts[Idx] = IE->getOperand(1);
+ ++NumFound;
+ }
+ V = IE->getOperand(0);
+ }
+
+ // Every element must be the same base pointer plus a constant byte offset
+ unsigned IdxWidth = DL.getIndexTypeSizeInBits(VecTy->getElementType());
+ Value *Base = nullptr;
+ SmallVector<APInt> Offsets;
+ for (Value *Elt : Elts) {
+ APInt Offset(IdxWidth, 0);
+ Value *EltBase =
+ Elt->stripAndAccumulateConstantOffsets(DL, Offset,
+ /*AllowNonInbounds=*/true);
+ if (!Base)
+ Base = EltBase;
+ else if (Base != EltBase)
+ return nullptr;
+ Offsets.push_back(Offset);
+ }
+
+ // Stripping walks through addrspacecasts, so the base may live in a
+ // different address space than the pointer the extract produces.
+ if (Base->getType() != VecTy->getElementType())
+ return nullptr;
+
+ // The offsets must form an arithmetic sequence.
+ APInt Stride = Offsets[1] - Offsets[0];
+ for (unsigned I = 1; I != NumElts; ++I)
+ if (Offsets[I] - Offsets[0] != Stride * I)
+ return nullptr;
+
+ // Index off the common base, not off element 0: an element may be poison in
+ // a lane the extract never selects. The base is an operand of every element
+ // and the new GEP has no flags, so the result is never more poisonous.
+ Type *IdxTy = DL.getIndexType(VecTy->getElementType());
+ Constant *BaseOff = ConstantInt::get(IdxTy, Offsets[0]);
+ if (Stride.isZero())
+ return Offsets[0].isZero()
+ ? Base
+ : Builder.CreateGEP(Builder.getInt8Ty(), Base, BaseOff);
----------------
arsenm wrote:
Doesn't this use the simplifying folder? You shouldn't need to special case 0?
https://github.com/llvm/llvm-project/pull/217078
More information about the llvm-commits
mailing list