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