Skip to content

Conversation

@kasuga-fj
Copy link
Contributor

This patch replaces the delinearization function used in LoopCacheAnalysis, switching from one that depends on type information in GEPs to one that does not. Once this patch and #161822 are landed, we can delete tryDelinearizeFixedSize from Delienarization, which is a optimization heuristic guided by GEP type information. After Polly eliminates its use of getIndexExpressionsFromGEP, we will be able to completely delete GEP-driven heuristics from Delinearization.

@llvmbot llvmbot added the llvm:analysis Includes value tracking, cost tables and constant folding label Oct 23, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 23, 2025

@llvm/pr-subscribers-llvm-analysis

Author: Ryotaro Kasuga (kasuga-fj)

Changes

This patch replaces the delinearization function used in LoopCacheAnalysis, switching from one that depends on type information in GEPs to one that does not. Once this patch and #161822 are landed, we can delete tryDelinearizeFixedSize from Delienarization, which is a optimization heuristic guided by GEP type information. After Polly eliminates its use of getIndexExpressionsFromGEP, we will be able to completely delete GEP-driven heuristics from Delinearization.


Full diff: https://github.com/llvm/llvm-project/pull/164798.diff

3 Files Affected:

  • (modified) llvm/include/llvm/Analysis/LoopCacheAnalysis.h (+2-1)
  • (modified) llvm/lib/Analysis/LoopCacheAnalysis.cpp (+11-15)
  • (modified) llvm/test/Analysis/LoopCacheAnalysis/interchange-refcost-overflow.ll (+1-1)
diff --git a/llvm/include/llvm/Analysis/LoopCacheAnalysis.h b/llvm/include/llvm/Analysis/LoopCacheAnalysis.h
index 3e22487e5e349..70ccd8aaed20f 100644
--- a/llvm/include/llvm/Analysis/LoopCacheAnalysis.h
+++ b/llvm/include/llvm/Analysis/LoopCacheAnalysis.h
@@ -102,7 +102,8 @@ class IndexedReference {
 
   /// Attempt to delinearize \p AccessFn for fixed-size arrays.
   bool tryDelinearizeFixedSize(const SCEV *AccessFn,
-                               SmallVectorImpl<const SCEV *> &Subscripts);
+                               SmallVectorImpl<const SCEV *> &Subscripts,
+                               const SCEV *ElementSize);
 
   /// Return true if the index reference is invariant with respect to loop \p L.
   bool isLoopInvariant(const Loop &L) const;
diff --git a/llvm/lib/Analysis/LoopCacheAnalysis.cpp b/llvm/lib/Analysis/LoopCacheAnalysis.cpp
index 050c32707596a..c1ce736bb51b0 100644
--- a/llvm/lib/Analysis/LoopCacheAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopCacheAnalysis.cpp
@@ -355,22 +355,18 @@ CacheCostTy IndexedReference::computeRefCost(const Loop &L,
 }
 
 bool IndexedReference::tryDelinearizeFixedSize(
-    const SCEV *AccessFn, SmallVectorImpl<const SCEV *> &Subscripts) {
-  SmallVector<int, 4> ArraySizes;
-  if (!tryDelinearizeFixedSizeImpl(&SE, &StoreOrLoadInst, AccessFn, Subscripts,
-                                   ArraySizes))
+    const SCEV *AccessFn, SmallVectorImpl<const SCEV *> &Subscripts,
+    const SCEV *ElementSize) {
+  const SCEV *Offset = SE.removePointerBase(AccessFn);
+  if (!delinearizeFixedSizeArray(SE, Offset, Subscripts, Sizes, ElementSize)) {
+    Sizes.clear();
     return false;
+  }
 
-  // Populate Sizes with scev expressions to be used in calculations later.
-  for (auto Idx : seq<unsigned>(1, Subscripts.size()))
-    Sizes.push_back(
-        SE.getConstant(Subscripts[Idx]->getType(), ArraySizes[Idx - 1]));
-
-  LLVM_DEBUG({
-    dbgs() << "Delinearized subscripts of fixed-size array\n"
-           << "GEP:" << *getLoadStorePointerOperand(&StoreOrLoadInst)
-           << "\n";
-  });
+  // Drop the last element of Sizes which is the same as ElementSize.
+  assert(!Sizes.empty() && Sizes.back() == ElementSize &&
+         "Expecting the last one to be the element size");
+  Sizes.pop_back();
   return true;
 }
 
@@ -397,7 +393,7 @@ bool IndexedReference::delinearize(const LoopInfo &LI) {
 
     bool IsFixedSize = false;
     // Try to delinearize fixed-size arrays.
-    if (tryDelinearizeFixedSize(AccessFn, Subscripts)) {
+    if (tryDelinearizeFixedSize(AccessFn, Subscripts, ElemSize)) {
       IsFixedSize = true;
       // The last element of Sizes is the element size.
       Sizes.push_back(ElemSize);
diff --git a/llvm/test/Analysis/LoopCacheAnalysis/interchange-refcost-overflow.ll b/llvm/test/Analysis/LoopCacheAnalysis/interchange-refcost-overflow.ll
index 7b6529601da32..30554d08a6181 100644
--- a/llvm/test/Analysis/LoopCacheAnalysis/interchange-refcost-overflow.ll
+++ b/llvm/test/Analysis/LoopCacheAnalysis/interchange-refcost-overflow.ll
@@ -9,8 +9,8 @@
 ;       A[c][d][d] = 0;
 ; }
 
-; CHECK: Loop 'outer.loop' has cost = 9223372036854775807
 ; CHECK: Loop 'inner.loop' has cost = 9223372036854775807
+; CHECK: Loop 'outer.loop' has cost = 10000
 
 @A = local_unnamed_addr global [11 x [11 x [11 x i32]]] zeroinitializer, align 16
 

Comment on lines -12 to 14

; CHECK: Loop 'outer.loop' has cost = 9223372036854775807
; CHECK: Loop 'inner.loop' has cost = 9223372036854775807
; CHECK: Loop 'outer.loop' has cost = 10000

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was added in #111807. Based on the description of the PR, the test appears to ensure that no assertion errors are triggered, so I believe this change is not particularly significant.

Copy link
Member

@Meinersbur Meinersbur Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sjoerdmeijer Can you confirm? Seems that it is basically ceiling the cost number to UINT64_MAX, so inner.loop is still tresting that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:analysis Includes value tracking, cost tables and constant folding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants