@@ -728,11 +728,6 @@ class AccessAnalysis {
728
728
729
729
MemAccessInfoList &getDependenciesToCheck () { return CheckDeps; }
730
730
731
- const DenseMap<Value *, SmallVector<const Value *, 16 >> &
732
- getUnderlyingObjects () {
733
- return UnderlyingObjects;
734
- }
735
-
736
731
private:
737
732
typedef MapVector<MemAccessInfo, SmallSetVector<Type *, 1 >> PtrAccessMap;
738
733
@@ -1459,22 +1454,23 @@ static bool isNoWrapAddRec(Value *Ptr, const SCEVAddRecExpr *AR,
1459
1454
}
1460
1455
1461
1456
// / Check whether the access through \p Ptr has a constant stride.
1462
- std::optional<int64_t > llvm::getPtrStride (PredicatedScalarEvolution &PSE,
1463
- Type *AccessTy, Value *Ptr ,
1464
- const Loop *Lp,
1465
- const DenseMap<Value *, const SCEV *> &StridesMap,
1466
- bool Assume, bool ShouldCheckWrap) {
1457
+ std::optional<int64_t >
1458
+ llvm::getPtrStride (PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr ,
1459
+ const Loop *Lp,
1460
+ const DenseMap<Value *, const SCEV *> &StridesMap,
1461
+ bool Assume, bool ShouldCheckWrap) {
1462
+ const SCEV *PtrScev = replaceSymbolicStrideSCEV (PSE, StridesMap, Ptr );
1463
+ if (PSE.getSE ()->isLoopInvariant (PtrScev, Lp))
1464
+ return {0 };
1465
+
1467
1466
Type *Ty = Ptr ->getType ();
1468
1467
assert (Ty->isPointerTy () && " Unexpected non-ptr" );
1469
-
1470
1468
if (isa<ScalableVectorType>(AccessTy)) {
1471
1469
LLVM_DEBUG (dbgs () << " LAA: Bad stride - Scalable object: " << *AccessTy
1472
1470
<< " \n " );
1473
1471
return std::nullopt;
1474
1472
}
1475
1473
1476
- const SCEV *PtrScev = replaceSymbolicStrideSCEV (PSE, StridesMap, Ptr );
1477
-
1478
1474
const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PtrScev);
1479
1475
if (Assume && !AR)
1480
1476
AR = PSE.getAsAddRec (Ptr );
@@ -1899,24 +1895,12 @@ static bool areStridedAccessesIndependent(uint64_t Distance, uint64_t Stride,
1899
1895
return ScaledDist % Stride;
1900
1896
}
1901
1897
1902
- // / Returns true if any of the underlying objects has a loop varying address,
1903
- // / i.e. may change in \p L.
1904
- static bool
1905
- isLoopVariantIndirectAddress (ArrayRef<const Value *> UnderlyingObjects,
1906
- ScalarEvolution &SE, const Loop *L) {
1907
- return any_of (UnderlyingObjects, [&SE, L](const Value *UO) {
1908
- return !SE.isLoopInvariant (SE.getSCEV (const_cast <Value *>(UO)), L);
1909
- });
1910
- }
1911
-
1912
1898
std::variant<MemoryDepChecker::Dependence::DepType,
1913
1899
MemoryDepChecker::DepDistanceStrideAndSizeInfo>
1914
1900
MemoryDepChecker::getDependenceDistanceStrideAndSize (
1915
1901
const AccessAnalysis::MemAccessInfo &A, Instruction *AInst,
1916
- const AccessAnalysis::MemAccessInfo &B, Instruction *BInst,
1917
- const DenseMap<Value *, SmallVector<const Value *, 16 >>
1918
- &UnderlyingObjects) {
1919
- auto &DL = InnermostLoop->getHeader ()->getDataLayout ();
1902
+ const AccessAnalysis::MemAccessInfo &B, Instruction *BInst) {
1903
+ const auto &DL = InnermostLoop->getHeader ()->getDataLayout ();
1920
1904
auto &SE = *PSE.getSE ();
1921
1905
auto [APtr, AIsWrite] = A;
1922
1906
auto [BPtr, BIsWrite] = B;
@@ -1933,39 +1917,30 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
1933
1917
BPtr->getType ()->getPointerAddressSpace ())
1934
1918
return MemoryDepChecker::Dependence::Unknown;
1935
1919
1936
- int64_t StrideAPtr =
1937
- getPtrStride (PSE, ATy, APtr, InnermostLoop, SymbolicStrides, true )
1938
- .value_or (0 );
1939
- int64_t StrideBPtr =
1940
- getPtrStride (PSE, BTy, BPtr, InnermostLoop, SymbolicStrides, true )
1941
- .value_or (0 );
1920
+ std::optional<int64_t > StrideAPtr =
1921
+ getPtrStride (PSE, ATy, APtr, InnermostLoop, SymbolicStrides, true , true );
1922
+ std::optional<int64_t > StrideBPtr =
1923
+ getPtrStride (PSE, BTy, BPtr, InnermostLoop, SymbolicStrides, true , true );
1942
1924
1943
1925
const SCEV *Src = PSE.getSCEV (APtr);
1944
1926
const SCEV *Sink = PSE.getSCEV (BPtr);
1945
1927
1946
1928
// If the induction step is negative we have to invert source and sink of the
1947
1929
// dependence when measuring the distance between them. We should not swap
1948
1930
// AIsWrite with BIsWrite, as their uses expect them in program order.
1949
- if (StrideAPtr < 0 ) {
1931
+ if (StrideAPtr && *StrideAPtr < 0 ) {
1950
1932
std::swap (Src, Sink);
1951
1933
std::swap (AInst, BInst);
1934
+ std::swap (StrideAPtr, StrideBPtr);
1952
1935
}
1953
1936
1954
1937
const SCEV *Dist = SE.getMinusSCEV (Sink, Src);
1955
1938
1956
1939
LLVM_DEBUG (dbgs () << " LAA: Src Scev: " << *Src << " Sink Scev: " << *Sink
1957
- << " (Induction step: " << StrideAPtr << " ) \n " );
1940
+ << " \n " );
1958
1941
LLVM_DEBUG (dbgs () << " LAA: Distance for " << *AInst << " to " << *BInst
1959
1942
<< " : " << *Dist << " \n " );
1960
1943
1961
- // Needs accesses where the addresses of the accessed underlying objects do
1962
- // not change within the loop.
1963
- if (isLoopVariantIndirectAddress (UnderlyingObjects.find (APtr)->second , SE,
1964
- InnermostLoop) ||
1965
- isLoopVariantIndirectAddress (UnderlyingObjects.find (BPtr)->second , SE,
1966
- InnermostLoop))
1967
- return MemoryDepChecker::Dependence::IndirectUnsafe;
1968
-
1969
1944
// Check if we can prove that Sink only accesses memory after Src's end or
1970
1945
// vice versa. At the moment this is limited to cases where either source or
1971
1946
// sink are loop invariant to avoid compile-time increases. This is not
@@ -1987,12 +1962,33 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
1987
1962
}
1988
1963
}
1989
1964
1990
- // Need accesses with constant strides and the same direction. We don't want
1991
- // to vectorize "A[B[i]] += ..." and similar code or pointer arithmetic that
1992
- // could wrap in the address space.
1993
- if (!StrideAPtr || !StrideBPtr || (StrideAPtr > 0 && StrideBPtr < 0 ) ||
1994
- (StrideAPtr < 0 && StrideBPtr > 0 )) {
1965
+ // Need accesses with constant strides and the same direction for further
1966
+ // dependence analysis. We don't want to vectorize "A[B[i]] += ..." and
1967
+ // similar code or pointer arithmetic that could wrap in the address space.
1968
+
1969
+ // If either Src or Sink are not strided (i.e. not a non-wrapping AddRec) and
1970
+ // not loop-invariant (stride will be 0 in that case), we cannot analyze the
1971
+ // dependence further and also cannot generate runtime checks.
1972
+ if (!StrideAPtr || !StrideBPtr) {
1995
1973
LLVM_DEBUG (dbgs () << " Pointer access with non-constant stride\n " );
1974
+ return MemoryDepChecker::Dependence::IndirectUnsafe;
1975
+ }
1976
+
1977
+ int64_t StrideAPtrInt = *StrideAPtr;
1978
+ int64_t StrideBPtrInt = *StrideBPtr;
1979
+ LLVM_DEBUG (dbgs () << " LAA: Src induction step: " << StrideAPtrInt
1980
+ << " Sink induction step: " << StrideBPtrInt << " \n " );
1981
+ // At least Src or Sink are loop invariant and the other is strided or
1982
+ // invariant. We can generate a runtime check to disambiguate the accesses.
1983
+ if (StrideAPtrInt == 0 || StrideBPtrInt == 0 )
1984
+ return MemoryDepChecker::Dependence::Unknown;
1985
+
1986
+ // Both Src and Sink have a constant stride, check if they are in the same
1987
+ // direction.
1988
+ if ((StrideAPtrInt > 0 && StrideBPtrInt < 0 ) ||
1989
+ (StrideAPtrInt < 0 && StrideBPtrInt > 0 )) {
1990
+ LLVM_DEBUG (
1991
+ dbgs () << " Pointer access with strides in different directions\n " );
1996
1992
return MemoryDepChecker::Dependence::Unknown;
1997
1993
}
1998
1994
@@ -2001,22 +1997,20 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
2001
1997
DL.getTypeStoreSizeInBits (ATy) == DL.getTypeStoreSizeInBits (BTy);
2002
1998
if (!HasSameSize)
2003
1999
TypeByteSize = 0 ;
2004
- return DepDistanceStrideAndSizeInfo (Dist, std::abs (StrideAPtr ),
2005
- std::abs (StrideBPtr ), TypeByteSize,
2000
+ return DepDistanceStrideAndSizeInfo (Dist, std::abs (StrideAPtrInt ),
2001
+ std::abs (StrideBPtrInt ), TypeByteSize,
2006
2002
AIsWrite, BIsWrite);
2007
2003
}
2008
2004
2009
- MemoryDepChecker::Dependence::DepType MemoryDepChecker::isDependent (
2010
- const MemAccessInfo &A, unsigned AIdx, const MemAccessInfo &B,
2011
- unsigned BIdx,
2012
- const DenseMap<Value *, SmallVector<const Value *, 16 >>
2013
- &UnderlyingObjects) {
2005
+ MemoryDepChecker::Dependence::DepType
2006
+ MemoryDepChecker::isDependent (const MemAccessInfo &A, unsigned AIdx,
2007
+ const MemAccessInfo &B, unsigned BIdx) {
2014
2008
assert (AIdx < BIdx && " Must pass arguments in program order" );
2015
2009
2016
2010
// Get the dependence distance, stride, type size and what access writes for
2017
2011
// the dependence between A and B.
2018
- auto Res = getDependenceDistanceStrideAndSize (
2019
- A, InstMap[AIdx], B, InstMap[BIdx], UnderlyingObjects );
2012
+ auto Res =
2013
+ getDependenceDistanceStrideAndSize ( A, InstMap[AIdx], B, InstMap[BIdx]);
2020
2014
if (std::holds_alternative<Dependence::DepType>(Res))
2021
2015
return std::get<Dependence::DepType>(Res);
2022
2016
@@ -2250,10 +2244,8 @@ MemoryDepChecker::Dependence::DepType MemoryDepChecker::isDependent(
2250
2244
return Dependence::BackwardVectorizable;
2251
2245
}
2252
2246
2253
- bool MemoryDepChecker::areDepsSafe (
2254
- DepCandidates &AccessSets, MemAccessInfoList &CheckDeps,
2255
- const DenseMap<Value *, SmallVector<const Value *, 16 >>
2256
- &UnderlyingObjects) {
2247
+ bool MemoryDepChecker::areDepsSafe (const DepCandidates &AccessSets,
2248
+ const MemAccessInfoList &CheckDeps) {
2257
2249
2258
2250
MinDepDistBytes = -1 ;
2259
2251
SmallPtrSet<MemAccessInfo, 8 > Visited;
@@ -2296,8 +2288,8 @@ bool MemoryDepChecker::areDepsSafe(
2296
2288
if (*I1 > *I2)
2297
2289
std::swap (A, B);
2298
2290
2299
- Dependence::DepType Type = isDependent (*A. first , A. second , *B. first ,
2300
- B. second , UnderlyingObjects );
2291
+ Dependence::DepType Type =
2292
+ isDependent (*A. first , A. second , *B. first , B. second );
2301
2293
mergeInStatus (Dependence::isSafeForVectorization (Type));
2302
2294
2303
2295
// Gather dependences unless we accumulated MaxDependences
@@ -2652,8 +2644,7 @@ bool LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
2652
2644
if (Accesses.isDependencyCheckNeeded ()) {
2653
2645
LLVM_DEBUG (dbgs () << " LAA: Checking memory dependencies\n " );
2654
2646
DepsAreSafe = DepChecker->areDepsSafe (DependentAccesses,
2655
- Accesses.getDependenciesToCheck (),
2656
- Accesses.getUnderlyingObjects ());
2647
+ Accesses.getDependenciesToCheck ());
2657
2648
2658
2649
if (!DepsAreSafe && DepChecker->shouldRetryWithRuntimeCheck ()) {
2659
2650
LLVM_DEBUG (dbgs () << " LAA: Retrying with memory checks\n " );
0 commit comments