Skip to content

Commit 2ccbf04

Browse files
committed
[LAA] Prepare to handle diff type sizes (NFC)
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 aa1a694 commit 2ccbf04

File tree

2 files changed

+54
-40
lines changed

2 files changed

+54
-40
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: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,17 +1949,21 @@ static bool isSafeDependenceDistance(const DataLayout &DL, ScalarEvolution &SE,
19491949

19501950
/// Check the dependence for two accesses with the same stride \p Stride.
19511951
/// \p Distance is the positive distance in bytes, and \p TypeByteSize is type
1952-
/// size in bytes.
1952+
/// size of source and sink in bytes.
1953+
/// TODO: Relax HasSameSize check in caller.
19531954
///
19541955
/// \returns true if they are independent.
1955-
static bool areStridedAccessesIndependent(uint64_t Distance, uint64_t Stride,
1956-
uint64_t TypeByteSize) {
1956+
static bool
1957+
areStridedAccessesIndependent(uint64_t Distance, uint64_t Stride,
1958+
std::pair<uint64_t, uint64_t> TypeByteSize) {
19571959
assert(Stride > 1 && "The stride must be greater than 1");
1958-
assert(TypeByteSize > 0 && "The type size in byte must be non-zero");
1960+
assert(TypeByteSize.first > 0 && TypeByteSize.second > 0 &&
1961+
"The type size in byte must be non-zero");
19591962
assert(Distance > 0 && "The distance must be non-zero");
19601963

1961-
// Skip if the distance is not multiple of type byte size.
1962-
if (Distance % TypeByteSize)
1964+
// Skip if the distance is not multiple of type byte size of either source or
1965+
// sink.
1966+
if (Distance % TypeByteSize.first || Distance % TypeByteSize.second)
19631967
return false;
19641968

19651969
// No dependence if the distance is not multiple of the stride.
@@ -2090,14 +2094,12 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
20902094
return MemoryDepChecker::Dependence::Unknown;
20912095
}
20922096

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.
20982097
uint64_t ASz = DL.getTypeAllocSize(ATy);
20992098
uint64_t BSz = DL.getTypeAllocSize(BTy);
2100-
uint64_t TypeByteSize = (AStoreSz == BStoreSz) ? BSz : 0;
2099+
2100+
// Both the source and sink sizes are neeeded in dependence checks, depending
2101+
// on the use.
2102+
std::pair<uint64_t, uint64_t> TypeByteSize(ASz, BSz);
21012103

21022104
uint64_t StrideAScaled = std::abs(StrideAPtrInt) * ASz;
21032105
uint64_t StrideBScaled = std::abs(StrideBPtrInt) * BSz;
@@ -2119,8 +2121,23 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
21192121
return Dependence::Unknown;
21202122
}
21212123

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

21262143
MemoryDepChecker::Dependence::DepType
@@ -2152,9 +2169,8 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
21522169
return std::get<Dependence::DepType>(Res);
21532170
}
21542171

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

21592175
ScalarEvolution &SE = *PSE.getSE();
21602176
auto &DL = InnermostLoop->getHeader()->getDataLayout();
@@ -2194,13 +2210,8 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
21942210
// Negative distances are not plausible dependencies.
21952211
if (SE.isKnownNonPositive(Dist)) {
21962212
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;
2213+
// Write to the same location with the same size.
2214+
return Dependence::Forward;
22042215
}
22052216

22062217
bool IsTrueDataDependence = (AIsWrite && !BIsWrite);
@@ -2218,7 +2229,7 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
22182229
: Dependence::Unknown;
22192230
}
22202231
if (!HasSameSize ||
2221-
couldPreventStoreLoadForward(ConstDist, TypeByteSize)) {
2232+
couldPreventStoreLoadForward(ConstDist, TypeByteSize.first)) {
22222233
LLVM_DEBUG(
22232234
dbgs() << "LAA: Forward but may prevent st->ld forwarding\n");
22242235
return Dependence::ForwardButPreventsForwarding;
@@ -2284,7 +2295,8 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
22842295
// We know that Dist is positive, but it may not be constant. Use the signed
22852296
// minimum for computations below, as this ensures we compute the closest
22862297
// possible dependence distance.
2287-
uint64_t MinDistanceNeeded = MaxStride * (MinNumIter - 1) + TypeByteSize;
2298+
uint64_t MinDistanceNeeded =
2299+
MaxStride * (MinNumIter - 1) + TypeByteSize.first;
22882300
if (MinDistanceNeeded > static_cast<uint64_t>(MinDistance)) {
22892301
if (!ConstDist) {
22902302
// For non-constant distances, we checked the lower bound of the
@@ -2312,14 +2324,15 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
23122324

23132325
bool IsTrueDataDependence = (!AIsWrite && BIsWrite);
23142326
if (IsTrueDataDependence && EnableForwardingConflictDetection && ConstDist &&
2315-
couldPreventStoreLoadForward(MinDistance, TypeByteSize, *CommonStride))
2327+
couldPreventStoreLoadForward(MinDistance, TypeByteSize.first,
2328+
*CommonStride))
23162329
return Dependence::BackwardVectorizableButPreventsForwarding;
23172330

23182331
uint64_t MaxVF = MinDepDistBytes / MaxStride;
23192332
LLVM_DEBUG(dbgs() << "LAA: Positive min distance " << MinDistance
23202333
<< " with max VF = " << MaxVF << '\n');
23212334

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

0 commit comments

Comments
 (0)