Skip to content

Commit 3f0b713

Browse files
committed
!fixup
1 parent b7f5e0d commit 3f0b713

File tree

1 file changed

+71
-57
lines changed

1 file changed

+71
-57
lines changed

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 71 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -140,52 +140,77 @@ bool VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
140140
return true;
141141
}
142142

143-
// Return true if \p A and \p B are known to not alias for all VFs in the plan,
144-
// checked via the distance between the accesses
145-
static bool isNoAliasViaDistance(VPReplicateRecipe *A, VPReplicateRecipe *B,
146-
ScalarEvolution &SE, const Loop &L,
147-
VPTypeAnalysis &TypeInfo) {
148-
if (A->getOpcode() != Instruction::Store ||
149-
B->getOpcode() != Instruction::Store)
150-
return false;
143+
/// Helper for extra no-alias checks via known-safe recipe and SCEV.
144+
class SinkStoreInfo {
145+
const SmallPtrSetImpl<VPRecipeBase *> &ExcludeRecipes;
146+
VPReplicateRecipe &GroupLeader;
147+
ScalarEvolution &SE;
148+
const Loop &L;
149+
VPTypeAnalysis &TypeInfo;
150+
151+
// Return true if \p A and \p B are known to not alias for all VFs in the
152+
// plan, checked via the distance between the accesses
153+
bool isNoAliasViaDistance(VPReplicateRecipe *A, VPReplicateRecipe *B) const {
154+
if (A->getOpcode() != Instruction::Store ||
155+
B->getOpcode() != Instruction::Store)
156+
return false;
151157

152-
VPValue *AddrA = A->getOperand(1);
153-
const SCEV *SCEVA = vputils::getSCEVExprForVPValue(AddrA, SE, &L);
154-
VPValue *AddrB = B->getOperand(1);
155-
const SCEV *SCEVB = vputils::getSCEVExprForVPValue(AddrB, SE, &L);
156-
if (isa<SCEVCouldNotCompute>(SCEVA) || isa<SCEVCouldNotCompute>(SCEVB))
157-
return false;
158+
VPValue *AddrA = A->getOperand(1);
159+
const SCEV *SCEVA = vputils::getSCEVExprForVPValue(AddrA, SE, &L);
160+
VPValue *AddrB = B->getOperand(1);
161+
const SCEV *SCEVB = vputils::getSCEVExprForVPValue(AddrB, SE, &L);
162+
if (isa<SCEVCouldNotCompute>(SCEVA) || isa<SCEVCouldNotCompute>(SCEVB))
163+
return false;
158164

159-
const APInt *Distance;
160-
if (!match(SE.getMinusSCEV(SCEVA, SCEVB), m_scev_APInt(Distance)))
161-
return false;
165+
const APInt *Distance;
166+
if (!match(SE.getMinusSCEV(SCEVA, SCEVB), m_scev_APInt(Distance)))
167+
return false;
162168

163-
const DataLayout &DL = L.getHeader()->getModule()->getDataLayout();
164-
Type *TyA = TypeInfo.inferScalarType(A->getOperand(0));
165-
uint64_t SizeA = DL.getTypeStoreSize(TyA);
166-
Type *TyB = TypeInfo.inferScalarType(B->getOperand(0));
167-
uint64_t SizeB = DL.getTypeStoreSize(TyB);
168-
// Use the maximum store size to ensure no overlap from either direction.
169-
uint64_t MaxStoreSize = std::max(SizeA, SizeB);
170-
171-
auto VFs = B->getParent()->getPlan()->vectorFactors();
172-
ElementCount MaxVF = *max_element(VFs, ElementCount::isKnownLT);
173-
return Distance->abs().uge(
174-
MaxVF.multiplyCoefficientBy(MaxStoreSize).getFixedValue());
175-
}
169+
const DataLayout &DL = L.getHeader()->getModule()->getDataLayout();
170+
Type *TyA = TypeInfo.inferScalarType(A->getOperand(0));
171+
uint64_t SizeA = DL.getTypeStoreSize(TyA);
172+
Type *TyB = TypeInfo.inferScalarType(B->getOperand(0));
173+
uint64_t SizeB = DL.getTypeStoreSize(TyB);
174+
// Use the maximum store size to ensure no overlap from either direction.
175+
// Currently only handles fixed sizes, as it is only used for
176+
// replicating VPReplicateRecipes.
177+
uint64_t MaxStoreSize = std::max(SizeA, SizeB);
178+
179+
auto VFs = B->getParent()->getPlan()->vectorFactors();
180+
ElementCount MaxVF = *max_element(VFs, ElementCount::isKnownLT);
181+
return Distance->abs().uge(
182+
MaxVF.multiplyCoefficientBy(MaxStoreSize).getFixedValue());
183+
}
184+
185+
public:
186+
SinkStoreInfo(const SmallPtrSetImpl<VPRecipeBase *> &ExcludeRecipes,
187+
VPReplicateRecipe &GroupLeader, ScalarEvolution &SE,
188+
const Loop &L, VPTypeAnalysis &TypeInfo)
189+
: ExcludeRecipes(ExcludeRecipes), GroupLeader(GroupLeader), SE(SE), L(L),
190+
TypeInfo(TypeInfo) {}
191+
192+
/// Return true if \p R should be skipped during alias checking, either
193+
/// because it's in the exclude set or because no-alias can be proven via
194+
/// SCEV.
195+
bool shouldSkip(VPRecipeBase &R) const {
196+
if (ExcludeRecipes.contains(&R))
197+
return true;
198+
if (auto *Store = dyn_cast<VPReplicateRecipe>(&R))
199+
return isNoAliasViaDistance(Store, &GroupLeader);
200+
return false;
201+
}
202+
};
176203

177-
// Check if a memory operation doesn't alias with memory operations in blocks
178-
// between FirstBB and LastBB using scoped noalias metadata. If \p CheckReads is
179-
// false, we only check recipes that may write to memory. Otherwise we check
180-
// recipes that both read and write memory. If a \p GroupLeader is passed, SCEV
181-
// is used to try to prove no-alias between \p GroupLeader and other replicate
182-
// recipes.
204+
/// Check if a memory operation doesn't alias with memory operations in blocks
205+
/// between \p FirstBB and \p LastBB using scoped noalias metadata. If
206+
/// \p SinkInfo is std::nullopt, only recipes that may write to memory are
207+
/// checked (for load hoisting). Otherwise recipes that both read and write
208+
/// memory are checked, and SCEV is used to prove no-alias between the group
209+
/// leader and other replicate recipes (for store sinking).
183210
static bool canHoistOrSinkWithNoAliasCheck(
184211
const MemoryLocation &MemLoc, VPBasicBlock *FirstBB, VPBasicBlock *LastBB,
185-
bool CheckReads,
186-
const SmallPtrSetImpl<VPRecipeBase *> *ExcludeRecipes = nullptr,
187-
VPReplicateRecipe *GroupLeader = nullptr, ScalarEvolution *SE = nullptr,
188-
const Loop *L = nullptr, VPTypeAnalysis *TypeInfo = nullptr) {
212+
std::optional<SinkStoreInfo> SinkInfo = std::nullopt) {
213+
bool CheckReads = SinkInfo.has_value();
189214
if (!MemLoc.AATags.Scope)
190215
return false;
191216

@@ -197,22 +222,13 @@ static bool canHoistOrSinkWithNoAliasCheck(
197222
"Expected at most one successor in block chain");
198223
auto *VPBB = cast<VPBasicBlock>(Block);
199224
for (VPRecipeBase &R : *VPBB) {
200-
if (ExcludeRecipes && ExcludeRecipes->contains(&R))
225+
if (SinkInfo && SinkInfo->shouldSkip(R))
201226
continue;
202227

203228
// Skip recipes that don't need checking.
204229
if (!R.mayWriteToMemory() && !(CheckReads && R.mayReadFromMemory()))
205230
continue;
206231

207-
// For stores, check if we can use SCEV to prove no-alias with the group
208-
// leader (all members of the group write to the same address with the
209-
// same size).
210-
if (auto *Store = dyn_cast<VPReplicateRecipe>(&R)) {
211-
if (GroupLeader &&
212-
isNoAliasViaDistance(Store, GroupLeader, *SE, *L, *TypeInfo))
213-
continue;
214-
}
215-
216232
auto Loc = vputils::getMemoryLocation(R);
217233
if (!Loc)
218234
// Conservatively assume aliasing for memory operations without
@@ -4321,8 +4337,7 @@ void VPlanTransforms::hoistPredicatedLoads(VPlan &Plan, ScalarEvolution &SE,
43214337

43224338
// Check that the load doesn't alias with stores between first and last.
43234339
auto LoadLoc = vputils::getMemoryLocation(*EarliestLoad);
4324-
if (!LoadLoc || !canHoistOrSinkWithNoAliasCheck(*LoadLoc, FirstBB, LastBB,
4325-
/*CheckReads=*/false))
4340+
if (!LoadLoc || !canHoistOrSinkWithNoAliasCheck(*LoadLoc, FirstBB, LastBB))
43264341
continue;
43274342

43284343
// Collect common metadata from all loads in the group.
@@ -4350,7 +4365,7 @@ void VPlanTransforms::hoistPredicatedLoads(VPlan &Plan, ScalarEvolution &SE,
43504365

43514366
static bool
43524367
canSinkStoreWithNoAliasCheck(ArrayRef<VPReplicateRecipe *> StoresToSink,
4353-
ScalarEvolution *SE, const Loop *L,
4368+
ScalarEvolution &SE, const Loop &L,
43544369
VPTypeAnalysis &TypeInfo) {
43554370
auto StoreLoc = vputils::getMemoryLocation(*StoresToSink.front());
43564371
if (!StoreLoc || !StoreLoc->AATags.Scope)
@@ -4363,9 +4378,8 @@ canSinkStoreWithNoAliasCheck(ArrayRef<VPReplicateRecipe *> StoresToSink,
43634378

43644379
VPBasicBlock *FirstBB = StoresToSink.front()->getParent();
43654380
VPBasicBlock *LastBB = StoresToSink.back()->getParent();
4366-
return canHoistOrSinkWithNoAliasCheck(*StoreLoc, FirstBB, LastBB,
4367-
/*CheckReads=*/true, &StoresToSinkSet,
4368-
StoresToSink[0], SE, L, &TypeInfo);
4381+
SinkStoreInfo Info(StoresToSinkSet, *StoresToSink[0], SE, L, TypeInfo);
4382+
return canHoistOrSinkWithNoAliasCheck(*StoreLoc, FirstBB, LastBB, Info);
43694383
}
43704384

43714385
void VPlanTransforms::sinkPredicatedStores(VPlan &Plan, ScalarEvolution &SE,
@@ -4383,7 +4397,7 @@ void VPlanTransforms::sinkPredicatedStores(VPlan &Plan, ScalarEvolution &SE,
43834397
return VPDT.properlyDominates(A, B);
43844398
});
43854399

4386-
if (!canSinkStoreWithNoAliasCheck(Group, &SE, L, TypeInfo))
4400+
if (!canSinkStoreWithNoAliasCheck(Group, SE, *L, TypeInfo))
43874401
continue;
43884402

43894403
// Use the last (most dominated) store's location for the unconditional

0 commit comments

Comments
 (0)