[llvm] [VPlan] Use SCEV to prove non-aliasing for stores at different offsets. (PR #170347)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 9 06:27:11 PST 2025
================
@@ -139,14 +140,77 @@ bool VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
return true;
}
-// Check if a memory operation doesn't alias with memory operations in blocks
-// between FirstBB and LastBB using scoped noalias metadata.
-// For load hoisting, we only check writes in one direction.
-// For store sinking, we check both reads and writes bidirectionally.
+/// Helper for extra no-alias checks via known-safe recipe and SCEV.
+class SinkStoreInfo {
+ const SmallPtrSetImpl<VPRecipeBase *> &ExcludeRecipes;
+ VPReplicateRecipe &GroupLeader;
+ ScalarEvolution &SE;
+ const Loop &L;
+ VPTypeAnalysis &TypeInfo;
+
+ // Return true if \p A and \p B are known to not alias for all VFs in the
+ // plan, checked via the distance between the accesses
+ bool isNoAliasViaDistance(VPReplicateRecipe *A, VPReplicateRecipe *B) const {
+ if (A->getOpcode() != Instruction::Store ||
+ B->getOpcode() != Instruction::Store)
+ return false;
+
+ VPValue *AddrA = A->getOperand(1);
+ const SCEV *SCEVA = vputils::getSCEVExprForVPValue(AddrA, SE, &L);
+ VPValue *AddrB = B->getOperand(1);
+ const SCEV *SCEVB = vputils::getSCEVExprForVPValue(AddrB, SE, &L);
+ if (isa<SCEVCouldNotCompute>(SCEVA) || isa<SCEVCouldNotCompute>(SCEVB))
+ return false;
+
+ const APInt *Distance;
+ if (!match(SE.getMinusSCEV(SCEVA, SCEVB), m_scev_APInt(Distance)))
+ return false;
+
+ const DataLayout &DL = L.getHeader()->getModule()->getDataLayout();
+ Type *TyA = TypeInfo.inferScalarType(A->getOperand(0));
+ uint64_t SizeA = DL.getTypeStoreSize(TyA);
+ Type *TyB = TypeInfo.inferScalarType(B->getOperand(0));
+ uint64_t SizeB = DL.getTypeStoreSize(TyB);
+ // Use the maximum store size to ensure no overlap from either direction.
+ // Currently only handles fixed sizes, as it is only used for
+ // replicating VPReplicateRecipes.
+ uint64_t MaxStoreSize = std::max(SizeA, SizeB);
+
+ auto VFs = B->getParent()->getPlan()->vectorFactors();
+ ElementCount MaxVF = *max_element(VFs, ElementCount::isKnownLT);
+ return Distance->abs().uge(
+ MaxVF.multiplyCoefficientBy(MaxStoreSize).getFixedValue());
+ }
+
+public:
+ SinkStoreInfo(const SmallPtrSetImpl<VPRecipeBase *> &ExcludeRecipes,
+ VPReplicateRecipe &GroupLeader, ScalarEvolution &SE,
+ const Loop &L, VPTypeAnalysis &TypeInfo)
+ : ExcludeRecipes(ExcludeRecipes), GroupLeader(GroupLeader), SE(SE), L(L),
+ TypeInfo(TypeInfo) {}
+
+ /// Return true if \p R should be skipped during alias checking, either
+ /// because it's in the exclude set or because no-alias can be proven via
+ /// SCEV.
+ bool shouldSkip(VPRecipeBase &R) const {
+ if (ExcludeRecipes.contains(&R))
+ return true;
+ if (auto *Store = dyn_cast<VPReplicateRecipe>(&R))
+ return isNoAliasViaDistance(Store, &GroupLeader);
+ return false;
----------------
fhahn wrote:
Done thanks
https://github.com/llvm/llvm-project/pull/170347
More information about the llvm-commits
mailing list