Skip to content

Commit 31a552d

Browse files
authored
[LoopCacheAnalysis] Replace delinearization for fixed size array (#164798)
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 an 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.
1 parent db5eedd commit 31a552d

File tree

4 files changed

+38
-27
lines changed

4 files changed

+38
-27
lines changed

llvm/include/llvm/Analysis/LoopCacheAnalysis.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ class IndexedReference {
102102

103103
/// Attempt to delinearize \p AccessFn for fixed-size arrays.
104104
bool tryDelinearizeFixedSize(const SCEV *AccessFn,
105-
SmallVectorImpl<const SCEV *> &Subscripts);
105+
SmallVectorImpl<const SCEV *> &Subscripts,
106+
const SCEV *ElementSize);
106107

107108
/// Return true if the index reference is invariant with respect to loop \p L.
108109
bool isLoopInvariant(const Loop &L) const;

llvm/lib/Analysis/LoopCacheAnalysis.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -355,22 +355,22 @@ CacheCostTy IndexedReference::computeRefCost(const Loop &L,
355355
}
356356

357357
bool IndexedReference::tryDelinearizeFixedSize(
358-
const SCEV *AccessFn, SmallVectorImpl<const SCEV *> &Subscripts) {
359-
SmallVector<int, 4> ArraySizes;
360-
if (!tryDelinearizeFixedSizeImpl(&SE, &StoreOrLoadInst, AccessFn, Subscripts,
361-
ArraySizes))
358+
const SCEV *AccessFn, SmallVectorImpl<const SCEV *> &Subscripts,
359+
const SCEV *ElementSize) {
360+
const SCEV *Offset = SE.removePointerBase(AccessFn);
361+
if (!delinearizeFixedSizeArray(SE, Offset, Subscripts, Sizes, ElementSize)) {
362+
Sizes.clear();
362363
return false;
364+
}
363365

364-
// Populate Sizes with scev expressions to be used in calculations later.
365-
for (auto Idx : seq<unsigned>(1, Subscripts.size()))
366-
Sizes.push_back(
367-
SE.getConstant(Subscripts[Idx]->getType(), ArraySizes[Idx - 1]));
368-
369-
LLVM_DEBUG({
370-
dbgs() << "Delinearized subscripts of fixed-size array\n"
371-
<< "GEP:" << *getLoadStorePointerOperand(&StoreOrLoadInst)
372-
<< "\n";
373-
});
366+
// We expect Sizes and Subscipts have the same number of elements, and the
367+
// last element of Sizes is ElementSize. It is for ensuring consistency with
368+
// the load/store instruction being analyzed. It is not needed for further
369+
// analysis.
370+
// TODO: Maybe this property should be enforced in delinearizeFixedSizeArray.
371+
assert(!Sizes.empty() && Subscripts.size() == Sizes.size() &&
372+
Sizes.back() == ElementSize && "Unexpected delinearization result");
373+
Sizes.pop_back();
374374
return true;
375375
}
376376

@@ -397,7 +397,7 @@ bool IndexedReference::delinearize(const LoopInfo &LI) {
397397

398398
bool IsFixedSize = false;
399399
// Try to delinearize fixed-size arrays.
400-
if (tryDelinearizeFixedSize(AccessFn, Subscripts)) {
400+
if (tryDelinearizeFixedSize(AccessFn, Subscripts, ElemSize)) {
401401
IsFixedSize = true;
402402
// The last element of Sizes is the element size.
403403
Sizes.push_back(ElemSize);

llvm/test/Analysis/LoopCacheAnalysis/interchange-refcost-overflow.ll

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,45 @@
33
; For a loop with a very large iteration count, make sure the cost
44
; calculation does not overflow:
55
;
6-
; void a(int b) {
7-
; for (int c;; c += b)
6+
; void a() {
7+
; for (int c;; c += 2)
88
; for (long d = 0; d < -3ULL; d += 2ULL)
9-
; A[c][d][d] = 0;
9+
; for (long e = 0; e < -3ULL; e += 2ULL)
10+
; A[c][d][e] = 0;
1011
; }
1112

1213
; CHECK: Loop 'outer.loop' has cost = 9223372036854775807
14+
; CHECK: Loop 'middle.loop' has cost = 9223372036854775807
1315
; CHECK: Loop 'inner.loop' has cost = 9223372036854775807
1416

1517
@A = local_unnamed_addr global [11 x [11 x [11 x i32]]] zeroinitializer, align 16
1618

17-
define void @foo(i32 noundef %b) {
19+
define void @foo() {
1820
entry:
19-
%0 = sext i32 %b to i64
2021
br label %outer.loop
2122

2223
outer.loop:
2324
%indvars.iv = phi i64 [ %indvars.iv.next, %outer.loop.cleanup ], [ 0, %entry ]
24-
br label %inner.loop
25+
br label %middle.loop
2526

2627
outer.loop.cleanup:
27-
%indvars.iv.next = add nsw i64 %indvars.iv, %0
28+
%indvars.iv.next = add i64 %indvars.iv, 2
2829
br label %outer.loop
2930

31+
middle.loop:
32+
%middle.iv = phi i64 [ %middle.iv.next, %middle.loop.cleanup ], [ 0, %outer.loop ]
33+
br label %inner.loop
34+
35+
middle.loop.cleanup:
36+
%middle.iv.next = add nuw i64 %middle.iv, 2
37+
%ec.middle = icmp ult i64 %middle.iv, -5
38+
br i1 %ec.middle, label %middle.loop, label %outer.loop.cleanup
39+
3040
inner.loop:
31-
%inner.iv = phi i64 [ 0, %outer.loop ], [ %add, %inner.loop ]
32-
%arrayidx3 = getelementptr inbounds [11 x [11 x [11 x i32]]], ptr @A, i64 0, i64 %indvars.iv, i64 %inner.iv, i64 %inner.iv
41+
%inner.iv = phi i64 [ 0, %middle.loop ], [ %add, %inner.loop ]
42+
%arrayidx3 = getelementptr inbounds [11 x [11 x [11 x i32]]], ptr @A, i64 0, i64 %indvars.iv, i64 %middle.iv, i64 %inner.iv
3343
store i32 0, ptr %arrayidx3, align 4
3444
%add = add nuw i64 %inner.iv, 2
3545
%cmp = icmp ult i64 %inner.iv, -5
36-
br i1 %cmp, label %inner.loop, label %outer.loop.cleanup
46+
br i1 %cmp, label %inner.loop, label %middle.loop.cleanup
3747
}

llvm/test/Transforms/LoopInterchange/pr43326.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: opt < %s -passes=loop-interchange -cache-line-size=64 -pass-remarks-missed='loop-interchange' -pass-remarks-output=%t -S \
2-
; RUN: -verify-dom-info -verify-loop-info -verify-loop-lcssa -stats 2>&1
2+
; RUN: -verify-dom-info -verify-loop-info -verify-loop-lcssa -loop-interchange-profitabilities=ignore -stats 2>&1
33
; RUN: FileCheck --input-file=%t --check-prefix=REMARKS %s
44

55
@a = global i32 0

0 commit comments

Comments
 (0)