Skip to content

Commit 1e5f7f6

Browse files
authored
[LoopInterchange] Handle confused dependence correctly (#140709)
This patch fixes the handling of a confused `Dependence` object. Such an object doesn’t contain any information about dependencies, so we must process it conservatively. However, it was converted into a direction vector like `[I I ... I]`. As a result, it was treated as if there are no loop-carried dependencies, which can lead to illegal loop exchanges. Fixes #140238
1 parent 0c89cbb commit 1e5f7f6

File tree

4 files changed

+52
-3
lines changed

4 files changed

+52
-3
lines changed

llvm/lib/Transforms/Scalar/LoopInterchange.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,14 @@ static bool populateDependencyMatrix(CharMatrix &DepMatrix, unsigned Level,
209209
Direction = '*';
210210
Dep.push_back(Direction);
211211
}
212+
213+
// If the Dependence object doesn't have any information, fill the
214+
// dependency vector with '*'.
215+
if (D->isConfused()) {
216+
assert(Dep.empty() && "Expected empty dependency vector");
217+
Dep.assign(Level, '*');
218+
}
219+
212220
while (Dep.size() != Level) {
213221
Dep.push_back('I');
214222
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
; REQUIRES: asserts
2+
; RUN: opt < %s -passes=loop-interchange -verify-dom-info -verify-loop-info \
3+
; RUN: -disable-output -debug 2>&1 | FileCheck %s
4+
5+
;; In the following case, p0 and p1 may alias, so the direction vector must be [* *].
6+
;;
7+
;; void may_alias(float *p0, float *p1) {
8+
;; for (int i = 0; i < 4; i++)
9+
;; for (int j = 0; j < 4; j++)
10+
;; p0[4 * i + j] = p1[4 * j + i];
11+
;; }
12+
13+
; CHECK: Dependency matrix before interchange:
14+
; CHECK-NEXT: * *
15+
; CHECK-NEXT: Processing InnerLoopId = 1 and OuterLoopId = 0
16+
define void @may_alias(ptr %p0, ptr %p1) {
17+
entry:
18+
br label %for.i.header
19+
20+
for.i.header:
21+
%i = phi i32 [ 0, %entry ], [ %i.inc, %for.i.latch ]
22+
br label %for.j
23+
24+
for.j:
25+
%j = phi i32 [ 0, %for.i.header ], [ %j.inc, %for.j ]
26+
%idx.0 = getelementptr inbounds [4 x [4 x float]], ptr %p0, i32 0, i32 %j, i32 %i
27+
%idx.1 = getelementptr inbounds [4 x [4 x float]], ptr %p1, i32 0, i32 %i, i32 %j
28+
%0 = load float, ptr %idx.0, align 4
29+
store float %0, ptr %idx.1, align 4
30+
%j.inc = add nuw nsw i32 %j, 1
31+
%cmp.j = icmp slt i32 %j.inc, 4
32+
br i1 %cmp.j, label %for.j, label %for.i.latch
33+
34+
for.i.latch:
35+
%i.inc = add nuw nsw i32 %i, 1
36+
%cmp.i = icmp slt i32 %i.inc, 4
37+
br i1 %cmp.i, label %for.i.header, label %exit
38+
39+
exit:
40+
ret void
41+
}

llvm/test/Transforms/LoopInterchange/pr43326-ideal-access-pattern.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
; Triply nested loop, should be able to do interchange three times
66
; to get the ideal access pattern.
7-
; void f(int e[10][10][10], int f[10][10][10]) {
7+
; void f(int e[restrict 10][10][10], int f[restrict 10][10][10]) {
88
; for (int a = 0; a < 10; a++) {
99
; for (int b = 0; b < 10; b++) {
1010
; for (int c = 0; c < 10; c++) {
@@ -35,7 +35,7 @@
3535
; REMARKS-NEXT: Name: Interchanged
3636
; REMARKS-NEXT: Function: pr43326-triply-nested
3737

38-
define void @pr43326-triply-nested(ptr %e, ptr %f) {
38+
define void @pr43326-triply-nested(ptr noalias %e, ptr noalias %f) {
3939
entry:
4040
br label %for.outermost.header
4141

llvm/test/Transforms/LoopInterchange/unique-dep-matrix.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
; RUN: opt < %s -passes=loop-interchange -S -debug 2>&1 | FileCheck %s
33

44
; CHECK: Dependency matrix before interchange:
5-
; CHECK-NEXT: I I
5+
; CHECK-NEXT: * *
66
; CHECK-NEXT: = *
77
; CHECK-NEXT: < *
88
; CHECK-NEXT: Processing InnerLoopId

0 commit comments

Comments
 (0)