[llvm] [VPlan] Use SCEV to prove non-aliasing for stores at different offsets. (PR #170347)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 2 11:55:35 PST 2025
================
@@ -139,14 +139,54 @@ bool VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
return true;
}
+// 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
+static bool isNoAliasViaDistance(VPReplicateRecipe *A, VPReplicateRecipe *B,
+ ScalarEvolution &SE, const Loop &L,
+ VPTypeAnalysis &TypeInfo) {
+ 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 SCEV *Distance = SE.getMinusSCEV(SCEVA, SCEVB);
+ auto *ConstDist = dyn_cast<SCEVConstant>(Distance);
+ if (!ConstDist)
+ return false;
+
+ const DataLayout &DL = L.getHeader()->getModule()->getDataLayout();
+ Type *TyA = TypeInfo.inferScalarType(A->getOperand(0));
+ TypeSize SizeA = DL.getTypeStoreSize(TyA);
+ Type *TyB = TypeInfo.inferScalarType(B->getOperand(0));
+ TypeSize SizeB = DL.getTypeStoreSize(TyB);
+
+ // Use the maximum store size to ensure no overlap from either direction.
+ uint64_t MaxStoreSize =
+ std::max(SizeA.getFixedValue(), SizeB.getFixedValue());
+ const APInt &DistValue = ConstDist->getAPInt();
+ auto VFs = B->getParent()->getPlan()->vectorFactors();
+ ElementCount MaxVF = *max_element(VFs, ElementCount::isKnownLT);
+ return DistValue.abs().uge(
+ MaxVF.multiplyCoefficientBy(MaxStoreSize).getFixedValue());
+}
+
// 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.
static bool canHoistOrSinkWithNoAliasCheck(
const MemoryLocation &MemLoc, VPBasicBlock *FirstBB, VPBasicBlock *LastBB,
bool CheckReads,
- const SmallPtrSetImpl<VPRecipeBase *> *ExcludeRecipes = nullptr) {
+ const SmallPtrSetImpl<VPRecipeBase *> *ExcludeRecipes = nullptr,
+ ScalarEvolution *SE = nullptr, const Loop *L = nullptr,
+ VPTypeAnalysis *TypeInfo = nullptr,
+ ArrayRef<VPReplicateRecipe *> MemOpsInGroup = {}) {
----------------
artagnon wrote:
Could document arguments? It's a bit mysterious at this point.
https://github.com/llvm/llvm-project/pull/170347
More information about the llvm-commits
mailing list