[llvm] [LAA] Refine stride checks for SCEVs during dependence analysis. (PR #99577)

Michael Kruse via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 25 04:13:27 PDT 2024


================
@@ -1987,11 +1979,47 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
     }
   }
 
-  // Need accesses with constant strides and the same direction. We don't want
-  // to vectorize "A[B[i]] += ..." and similar code or pointer arithmetic that
-  // could wrap in the address space.
-  if (!StrideAPtr || !StrideBPtr || (StrideAPtr > 0 && StrideBPtr < 0) ||
-      (StrideAPtr < 0 && StrideBPtr > 0)) {
+  // Need accesses with constant strides and the same direction for further
+  // dependence analysis. We don't want to vectorize "A[B[i]] += ..." and
+  // similar code or pointer arithmetic that could wrap in the address space.
+  //
+  // If Src or Sink are non-wrapping AddRecs, StrideAPtr and StrideBPtr contain
+  // a SCEV representing the stride of the SCEV. It may not be a known constant
+  // value though.
+
+  // If either Src or Sink are not strided (i.e. not a non-wrapping AddRec), we
+  // cannot analyze the dependence further.
+  if (!StrideAPtr || !StrideBPtr) {
+    bool SrcInvariant = SE.isLoopInvariant(Src, InnermostLoop);
+    bool SinkInvariant = SE.isLoopInvariant(Sink, InnermostLoop);
+    // If either Src or Sink are not loop invariant and not strided, the
+    // expression in the current iteration may overlap with any earlier or later
+    // iteration. This is not safe and we also cannot generate runtime checks to
+    // ensure safety. This includes expressions where an index is loaded in each
+    // iteration or wrapping AddRecs.
+    if ((!SrcInvariant && !StrideAPtr) || (!SinkInvariant && !StrideBPtr))
+      return MemoryDepChecker::Dependence::IndirectUnsafe;
----------------
Meinersbur wrote:

IIUC, this is the relevant change. An access must be strided or invariant for analysis. That's a good simplification over whatever `isLoopVariantIndirectAddress(UnderlyingObjects...)` does.

I would inverse the condition, to check the supported cases and fallback to the unsupported one (we may want to support more cases in the future):
```
// Can generate runtime check for strided and invariant (i.e. stride 0) accesses.
if ((SrcInvariant || StrideAPtr) && (SinkInvariant || StrideBPtr))
  MemoryDepChecker::Dependence::Unknown;

// Some case we do not support.
return MemoryDepChecker::Dependence::IndirectUnsafe;
```
(NB: Pretty weird to call the supported case "Unknown")

Since invariant means stride 0, why not make `getPtrStride` return 0 in that case? Seems like confusing `0` and "cannot determine stride" is the root cause of this problem.

https://github.com/llvm/llvm-project/pull/99577


More information about the llvm-commits mailing list