[llvm] [VectorCombine] Fold contiguous loads into a single vector load (PR #185736)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 3 06:56:17 PDT 2026
================
@@ -6120,6 +6055,167 @@ bool VectorCombine::shrinkPhiOfShuffles(Instruction &I) {
return true;
}
+/// Try to fold lanes assembled from contiguous vector-load elements into one
+/// load of the result type.
+///
+/// 1. Trace lanes:
+/// result lane 0 result lane 1 ... result lane N
+/// | | |
+/// +------- look through shuffles ---------+
+/// |
+/// source load + source lane
+///
+/// 2. Check layout:
+/// same base pointer and contiguous offsets?
+///
+/// 3. Model old cost:
+/// current op + unique loads + original GEPs
+///
+/// 4. Model new cost:
+/// ptradd(base, start byte offset) + one vector load
+///
+/// 5. Replace:
+/// if NewCost is cheaper
+///
+/// For example:
+///
+/// %p = getelementptr float, ptr %base, i64 4
+/// %v = load <4 x float>, ptr %p
+/// base+16 base+20 base+24 base+28
+/// lane 0 lane 1 lane 2 lane 3
+/// | |
+/// +---------+ contiguous
+/// |
+/// %r = shufflevector %v, poison, <2, 3>
+/// |
+/// v
+/// %q = getelementptr i8, ptr %base, i64 24
+/// %r = load <2 x float>, ptr %q
+bool VectorCombine::foldContiguousLoads(Instruction &I) {
+ auto *VT = dyn_cast<FixedVectorType>(I.getType());
+ if (!VT || I.use_empty())
+ return false;
+
+ Type *EltTy = VT->getElementType();
+ if (!DL->typeSizeEqualsStoreSize(EltTy))
+ return false;
+
+ uint64_t MaxInt64 =
+ static_cast<uint64_t>(std::numeric_limits<int64_t>::max());
+ uint64_t ElementSizeBits = DL->getTypeStoreSizeInBits(EltTy);
+ assert((ElementSizeBits <= MaxInt64) && "element size far too large?");
+ int64_t ElementSizeBitsI64 = static_cast<int64_t>(ElementSizeBits);
+ unsigned NumElts = VT->getNumElements();
+ Value *CommonBase = nullptr;
+ int64_t StartBitOffset = 0, FirstLoadByteOffset = 0;
+ LoadInst *FirstLI = nullptr;
+ SmallPtrSet<LoadInst *, 4> Loads;
+ for (unsigned Lane = 0; Lane < NumElts; ++Lane) {
+ // Step 1: Trace this result lane through shuffle users to find the source
+ // instruction and the lane selected from it.
+ InstLane IL = lookThroughShuffles(&I, Lane);
+ if (!IL.first)
+ return false;
+
+ auto *LI = dyn_cast<LoadInst>(IL.first);
+ if (!LI)
+ return false;
+
+ if (!LI->isSimple() || !LI->hasOneUse())
+ return false;
+
+ auto *LIVTy = dyn_cast<FixedVectorType>(LI->getType());
+ if (!LIVTy || LIVTy->getElementType() != EltTy)
+ return false;
+
+ if (LI->getParent() != I.getParent())
+ return false;
----------------
arsenm wrote:
All of the tests are single block functions, so this condition isn't tested
https://github.com/llvm/llvm-project/pull/185736
More information about the llvm-commits
mailing list