[llvm] [LSV] Merge contiguous chains across scalar types (PR #154069)

Anshil Gandhi via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 21 21:26:25 PDT 2025


================
@@ -467,6 +489,98 @@ bool Vectorizer::run() {
   return Changed;
 }
 
+Value *Vectorizer::insertCast(Value *Val, Type *DstTy) {
+  if (DL.getTypeSizeInBits(Val->getType()) == DL.getTypeSizeInBits(DstTy)) {
+    return Builder.CreateBitOrPointerCast(Val, DstTy, Val->getName() + ".bc");
+  }
+
+  // If the types are of different sizes and both are integers, we can use
+  // zext or sext to cast.
+  if (Val->getType()->isIntegerTy() && DstTy->isIntegerTy()) {
+    if (DL.getTypeSizeInBits(Val->getType()) < DL.getTypeSizeInBits(DstTy)) {
+      return Builder.CreateZExt(Val, DstTy, Val->getName() + ".bc");
+    }
+    return Builder.CreateTrunc(Val, DstTy, Val->getName() + ".bc");
+  }
+
+  return nullptr;
+}
+
+std::optional<APInt> Vectorizer::computeLeaderDelta(Instruction *I1,
+                                                    Instruction *I2) {
+  assert((isa<LoadInst>(I1) || isa<StoreInst>(I1)) &&
+         (isa<LoadInst>(I2) || isa<StoreInst>(I2)) &&
+         "computeLeaderDelta must be called with load or store instructions");
+  Instruction *CtxInst = I1->comesBefore(I2) ? I2 : I1;
+  const Value *Ptr1 = getLoadStorePointerOperand(I1);
+  const Value *Ptr2 = getLoadStorePointerOperand(I2);
+  return getConstantOffset(const_cast<Value *>(Ptr1), const_cast<Value *>(Ptr2),
+                           CtxInst);
+}
+
+bool Vectorizer::chainsOverlapAfterRebase(const Chain &A, const Chain &B,
+                                          const APInt &Delta) const {
+  for (const ChainElem &EB : B) {
+    APInt OffB = EB.OffsetFromLeader + Delta;
+    unsigned SizeB = DL.getTypeStoreSize(getLoadStoreType(EB.Inst));
+    APInt EndB = OffB + SizeB;
+    for (const ChainElem &EA : A) {
+      APInt OffA = EA.OffsetFromLeader;
+      unsigned SizeA = DL.getTypeStoreSize(getLoadStoreType(EA.Inst));
+      APInt EndA = OffA + SizeA;
+      if (OffB.slt(EndA) && OffA.slt(EndB))
+        return true;
+    }
+  }
+  return false;
+}
+
+bool Vectorizer::allElemsMatchTotalBits(const Chain &C, unsigned TotalBits,
+                                        const DataLayout &DL) {
+  return llvm::all_of(C, [&](const ChainElem &E) {
+    return DL.getTypeSizeInBits(getLoadStoreType(E.Inst)) == TotalBits;
+  });
+}
+
+void Vectorizer::rebaseChain(Chain &C, const APInt &Delta) {
+  for (ChainElem &E : C)
+    E.OffsetFromLeader += Delta;
+}
+
+void Vectorizer::normalizeChainToType(Chain &C, Type *CastTy) {
+  for (ChainElem &Elem : C) {
+    Instruction *Inst = Elem.Inst;
+    Type *OrigValTy = getLoadStoreType(Inst);
+    if (OrigValTy == CastTy)
+      continue;
+
+    if (auto *LI = dyn_cast<LoadInst>(Inst)) {
+      Builder.SetInsertPoint(LI);
+      LoadInst *NewLoad = Builder.CreateLoad(CastTy, LI->getPointerOperand(),
+                                             LI->getName() + ".mut");
+      copyMetadataForLoad(*NewLoad, *LI);
+      Value *CastBack = insertCast(NewLoad, OrigValTy);
+      if (!CastBack)
+        llvm_unreachable("Failed to insert cast");
+      LI->replaceAllUsesWith(CastBack);
+      ToErase.emplace_back(LI);
+      Elem.Inst = NewLoad;
+    } else if (auto *SI = dyn_cast<StoreInst>(Inst)) {
+      Builder.SetInsertPoint(SI);
+      Value *CastVal = insertCast(SI->getValueOperand(), CastTy);
+      if (!CastVal)
+        llvm_unreachable("Failed to insert cast");
+      StoreInst *NewStore =
+          Builder.CreateStore(CastVal, SI->getPointerOperand());
+      NewStore->setAlignment(SI->getAlign());
+      NewStore->setVolatile(SI->isVolatile());
+      copyMetadataForStore(*NewStore, *SI);
----------------
gandhi56 wrote:

The vectorization occurs after the new stores are inserted.

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


More information about the llvm-commits mailing list