Skip to content

Commit 1aded51

Browse files
authored
[LAA] Prepare to handle diff type sizes (NFC) (#122318)
As depend_diff_types shows, there are several places where the HasSameSize check can be relaxed for higher analysis precision. As a first step, return both the source size and the sink size from getDependenceDistanceStrideAndSize, along with a HasSameSize boolean for the moment.
1 parent cac3894 commit 1aded51

File tree

2 files changed

+47
-35
lines changed

2 files changed

+47
-35
lines changed

llvm/include/llvm/Analysis/LoopAccessAnalysis.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -413,29 +413,30 @@ class MemoryDepChecker {
413413
uint64_t MaxStride;
414414
std::optional<uint64_t> CommonStride;
415415

416-
/// TypeByteSize is either the common store size of both accesses, or 0 when
417-
/// store sizes mismatch.
418-
uint64_t TypeByteSize;
416+
/// TypeByteSize is a pair of alloc sizes of the source and sink.
417+
std::pair<uint64_t, uint64_t> TypeByteSize;
418+
419+
// HasSameSize is a boolean indicating whether the store sizes of the source
420+
// and sink are equal.
421+
// TODO: Remove this.
422+
bool HasSameSize;
419423

420424
bool AIsWrite;
421425
bool BIsWrite;
422426

423427
DepDistanceStrideAndSizeInfo(const SCEV *Dist, uint64_t MaxStride,
424428
std::optional<uint64_t> CommonStride,
425-
uint64_t TypeByteSize, bool AIsWrite,
426-
bool BIsWrite)
429+
std::pair<uint64_t, uint64_t> TypeByteSize,
430+
bool HasSameSize, bool AIsWrite, bool BIsWrite)
427431
: Dist(Dist), MaxStride(MaxStride), CommonStride(CommonStride),
428-
TypeByteSize(TypeByteSize), AIsWrite(AIsWrite), BIsWrite(BIsWrite) {}
432+
TypeByteSize(TypeByteSize), HasSameSize(HasSameSize),
433+
AIsWrite(AIsWrite), BIsWrite(BIsWrite) {}
429434
};
430435

431436
/// Get the dependence distance, strides, type size and whether it is a write
432-
/// for the dependence between A and B. Returns a DepType, if we can prove
433-
/// there's no dependence or the analysis fails. Outlined to lambda to limit
434-
/// he scope of various temporary variables, like A/BPtr, StrideA/BPtr and
435-
/// others. Returns either the dependence result, if it could already be
436-
/// determined, or a DepDistanceStrideAndSizeInfo struct, noting that
437-
/// TypeByteSize could be 0 when store sizes mismatch, and this should be
438-
/// checked in the caller.
437+
/// for the dependence between A and B. Returns either a DepType, the
438+
/// dependence result, if it could already be determined, or a
439+
/// DepDistanceStrideAndSizeInfo struct.
439440
std::variant<Dependence::DepType, DepDistanceStrideAndSizeInfo>
440441
getDependenceDistanceStrideAndSize(const MemAccessInfo &A, Instruction *AInst,
441442
const MemAccessInfo &B,

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,14 +2090,12 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
20902090
return MemoryDepChecker::Dependence::Unknown;
20912091
}
20922092

2093-
TypeSize AStoreSz = DL.getTypeStoreSize(ATy);
2094-
TypeSize BStoreSz = DL.getTypeStoreSize(BTy);
2095-
2096-
// If store sizes are not the same, set TypeByteSize to zero, so we can check
2097-
// it in the caller isDependent.
20982093
uint64_t ASz = DL.getTypeAllocSize(ATy);
20992094
uint64_t BSz = DL.getTypeAllocSize(BTy);
2100-
uint64_t TypeByteSize = (AStoreSz == BStoreSz) ? BSz : 0;
2095+
2096+
// Both the source and sink sizes are neeeded in dependence checks, depending
2097+
// on the use.
2098+
std::pair<uint64_t, uint64_t> TypeByteSize(ASz, BSz);
21012099

21022100
uint64_t StrideAScaled = std::abs(StrideAPtrInt) * ASz;
21032101
uint64_t StrideBScaled = std::abs(StrideBPtrInt) * BSz;
@@ -2119,8 +2117,23 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
21192117
return Dependence::Unknown;
21202118
}
21212119

2120+
// When the distance is possibly zero, we're reading/writing the same memory
2121+
// location: if the store sizes are not equal, fail with an unknown
2122+
// dependence.
2123+
TypeSize AStoreSz = DL.getTypeStoreSize(ATy);
2124+
TypeSize BStoreSz = DL.getTypeStoreSize(BTy);
2125+
if (AStoreSz != BStoreSz && !SE.isKnownNonZero(Dist)) {
2126+
LLVM_DEBUG(dbgs() << "LAA: possibly zero dependence distance with "
2127+
"different type sizes\n");
2128+
return Dependence::Unknown;
2129+
}
2130+
2131+
// TODO: Remove this.
2132+
bool HasSameSize = AStoreSz == BStoreSz;
2133+
21222134
return DepDistanceStrideAndSizeInfo(Dist, MaxStride, CommonStride,
2123-
TypeByteSize, AIsWrite, BIsWrite);
2135+
TypeByteSize, HasSameSize, AIsWrite,
2136+
BIsWrite);
21242137
}
21252138

21262139
MemoryDepChecker::Dependence::DepType
@@ -2152,9 +2165,8 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
21522165
return std::get<Dependence::DepType>(Res);
21532166
}
21542167

2155-
auto &[Dist, MaxStride, CommonStride, TypeByteSize, AIsWrite, BIsWrite] =
2156-
std::get<DepDistanceStrideAndSizeInfo>(Res);
2157-
bool HasSameSize = TypeByteSize > 0;
2168+
auto &[Dist, MaxStride, CommonStride, TypeByteSize, HasSameSize, AIsWrite,
2169+
BIsWrite] = std::get<DepDistanceStrideAndSizeInfo>(Res);
21582170

21592171
ScalarEvolution &SE = *PSE.getSE();
21602172
auto &DL = InnermostLoop->getHeader()->getDataLayout();
@@ -2180,7 +2192,8 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
21802192
// If the distance between accesses and their strides are known constants,
21812193
// check whether the accesses interlace each other.
21822194
if (ConstDist > 0 && CommonStride && CommonStride > 1 && HasSameSize &&
2183-
areStridedAccessesIndependent(ConstDist, *CommonStride, TypeByteSize)) {
2195+
areStridedAccessesIndependent(ConstDist, *CommonStride,
2196+
TypeByteSize.first)) {
21842197
LLVM_DEBUG(dbgs() << "LAA: Strided accesses are independent\n");
21852198
return Dependence::NoDep;
21862199
}
@@ -2194,13 +2207,9 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
21942207
// Negative distances are not plausible dependencies.
21952208
if (SE.isKnownNonPositive(Dist)) {
21962209
if (SE.isKnownNonNegative(Dist)) {
2197-
if (HasSameSize) {
2198-
// Write to the same location with the same size.
2199-
return Dependence::Forward;
2200-
}
2201-
LLVM_DEBUG(dbgs() << "LAA: possibly zero dependence difference but "
2202-
"different type sizes\n");
2203-
return Dependence::Unknown;
2210+
// Write to the same location with the same size.
2211+
assert(HasSameSize && "Accesses must have the same size");
2212+
return Dependence::Forward;
22042213
}
22052214

22062215
bool IsTrueDataDependence = (AIsWrite && !BIsWrite);
@@ -2218,7 +2227,7 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
22182227
: Dependence::Unknown;
22192228
}
22202229
if (!HasSameSize ||
2221-
couldPreventStoreLoadForward(ConstDist, TypeByteSize)) {
2230+
couldPreventStoreLoadForward(ConstDist, TypeByteSize.first)) {
22222231
LLVM_DEBUG(
22232232
dbgs() << "LAA: Forward but may prevent st->ld forwarding\n");
22242233
return Dependence::ForwardButPreventsForwarding;
@@ -2284,7 +2293,8 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
22842293
// We know that Dist is positive, but it may not be constant. Use the signed
22852294
// minimum for computations below, as this ensures we compute the closest
22862295
// possible dependence distance.
2287-
uint64_t MinDistanceNeeded = MaxStride * (MinNumIter - 1) + TypeByteSize;
2296+
uint64_t MinDistanceNeeded =
2297+
MaxStride * (MinNumIter - 1) + TypeByteSize.first;
22882298
if (MinDistanceNeeded > static_cast<uint64_t>(MinDistance)) {
22892299
if (!ConstDist) {
22902300
// For non-constant distances, we checked the lower bound of the
@@ -2312,14 +2322,15 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
23122322

23132323
bool IsTrueDataDependence = (!AIsWrite && BIsWrite);
23142324
if (IsTrueDataDependence && EnableForwardingConflictDetection && ConstDist &&
2315-
couldPreventStoreLoadForward(MinDistance, TypeByteSize, *CommonStride))
2325+
couldPreventStoreLoadForward(MinDistance, TypeByteSize.first,
2326+
*CommonStride))
23162327
return Dependence::BackwardVectorizableButPreventsForwarding;
23172328

23182329
uint64_t MaxVF = MinDepDistBytes / MaxStride;
23192330
LLVM_DEBUG(dbgs() << "LAA: Positive min distance " << MinDistance
23202331
<< " with max VF = " << MaxVF << '\n');
23212332

2322-
uint64_t MaxVFInBits = MaxVF * TypeByteSize * 8;
2333+
uint64_t MaxVFInBits = MaxVF * TypeByteSize.first * 8;
23232334
if (!ConstDist && MaxVFInBits < MaxTargetVectorWidthInBits) {
23242335
// For non-constant distances, we checked the lower bound of the dependence
23252336
// distance and the distance may be larger at runtime (and safe for

0 commit comments

Comments
 (0)