[llvm] [LoadStoreVectorizer] Support vectorization of mixed-type contiguous accesses (PR #177908)
Anshil Gandhi via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 14 10:53:30 PDT 2026
================
@@ -160,7 +155,67 @@ struct ChainElem {
ChainElem(Instruction *Inst, APInt OffsetFromLeader)
: Inst(std::move(Inst)), OffsetFromLeader(std::move(OffsetFromLeader)) {}
};
-using Chain = SmallVector<ChainElem, 1>;
+struct Chain : SmallVector<ChainElem, 1> {
+private:
+ Type *ElemTy = nullptr;
+
+public:
+ using SmallVector::SmallVector;
+
+ /// Return the GCD of the element sizes.
+ unsigned int computeGCDSize(const DataLayout &DL) const {
+ unsigned int GCDSize = 0;
+ for (const ChainElem &E : *this) {
+ Type *Ty = getLoadStoreType(E.Inst)->getScalarType();
+ unsigned Sz = DL.getTypeSizeInBits(Ty);
+ GCDSize = GCDSize == 0 ? Sz : std::gcd(GCDSize, Sz);
+ }
+ return GCDSize;
+ }
+
+ /// Gets the element type of the vector that the chain will load or store.
+ ///
+ /// The element type is determined by taking the GCD of the bitwidths of all
+ /// elements in the chain. Among types with this matching bitwidth, we prefer:
+ /// - A type that appears most frequently in the chain, to minimize casts.
+ /// - An integer type if the chain contains pointers, to avoid direct
+ /// pointer-to-floating-point conversions.
+ ///
+ /// \param C The chain of instructions to be vectorized.
+ /// \returns The chosen element type for the vectorized load or store.
+ Type *computeAndCacheElemTy(LLVMContext &Ctx, const DataLayout &DL) {
+ assert(!empty());
+ if (ElemTy)
+ return ElemTy;
+
+ unsigned GCDSize = computeGCDSize(DL);
+ bool HasPointers = llvm::any_of(*this, [&](ChainElem &E) {
+ return getLoadStoreType(E.Inst)->getScalarType()->isPointerTy();
+ });
+
+ // Among non-pointer types whose size matches the GCD, prefer the most
+ // common one to minimize bitcasts. If the chain contains pointers, only
+ // consider integer types (there's no direct FP-to-pointer cast).
+ DenseMap<Type *, unsigned> TypeCounts;
+ Type *BestTy = nullptr;
+ unsigned BestCount = 0;
+ for (const ChainElem &E : *this) {
+ Type *Ty = getLoadStoreType(E.Inst)->getScalarType();
+ if (Ty->isPointerTy() || DL.getTypeSizeInBits(Ty) != GCDSize ||
+ (HasPointers && !Ty->isIntegerTy()))
+ continue;
+ unsigned Count = ++TypeCounts[Ty];
+ if (Count > BestCount) {
+ BestCount = Count;
+ BestTy = Ty;
+ }
+ }
+
+ return ElemTy = BestTy ? BestTy : Type::getIntNTy(Ctx, GCDSize);
+ }
+
+ void setElemTy(Type *Ty) { ElemTy = Ty; }
----------------
gandhi56 wrote:
Removed `setElemTy` and made `ElemTy` private. `ElemTy` is now exclusively set using `computeAndCacheElemTy(..)` and is maintained within the `struct Chain`.
https://github.com/llvm/llvm-project/pull/177908
More information about the llvm-commits
mailing list