Skip to content

Commit 2978b20

Browse files
authored
[Delinearization] Add validation for large size arrays (#169902)
This patch adds a check in validation for delinearization to ensure that the offset calculation does not overflow. If it overflows, different array accesses (e.g., `A[0][0]` and `A[1][0]`) could map to the same linear index, leading to incorrect behavior. For fixed-size arrays, the check is relatively straightforward. However, for dynamic-size arrays (i.e., arrays where the size is not known at compile time), it's difficult to prove this statically, and it going to fail for almost all cases. Maybe we need to add some runtime checks or reasoning based on `inbounds` like LAA does. Fixes the test cases added in #169048.
1 parent 542a8f2 commit 2978b20

File tree

10 files changed

+143
-33
lines changed

10 files changed

+143
-33
lines changed

llvm/lib/Analysis/Delinearization.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,26 @@ bool llvm::validateDelinearizationResult(ScalarEvolution &SE,
747747
ArrayRef<const SCEV *> Sizes,
748748
ArrayRef<const SCEV *> Subscripts,
749749
const Value *Ptr) {
750+
// Sizes and Subscripts are as follows:
751+
//
752+
// Sizes: [UNK][S_2]...[S_n]
753+
// Subscripts: [I_1][I_2]...[I_n]
754+
//
755+
// where the size of the outermost dimension is unknown (UNK).
756+
757+
auto AddOverflow = [&](const SCEV *A, const SCEV *B) -> const SCEV * {
758+
if (!SE.willNotOverflow(Instruction::Add, /*IsSigned=*/true, A, B))
759+
return nullptr;
760+
return SE.getAddExpr(A, B);
761+
};
762+
763+
auto MulOverflow = [&](const SCEV *A, const SCEV *B) -> const SCEV * {
764+
if (!SE.willNotOverflow(Instruction::Mul, /*IsSigned=*/true, A, B))
765+
return nullptr;
766+
return SE.getMulExpr(A, B);
767+
};
768+
769+
// Range check: 0 <= I_k < S_k for k = 2..n.
750770
for (size_t I = 1; I < Sizes.size(); ++I) {
751771
const SCEV *Size = Sizes[I - 1];
752772
const SCEV *Subscript = Subscripts[I];
@@ -755,6 +775,49 @@ bool llvm::validateDelinearizationResult(ScalarEvolution &SE,
755775
if (!isKnownLessThan(&SE, Subscript, Size))
756776
return false;
757777
}
778+
779+
// The offset computation is as follows:
780+
//
781+
// Offset = I_n +
782+
// S_n * I_{n-1} +
783+
// ... +
784+
// (S_2 * ... * S_n) * I_1
785+
//
786+
// Regarding this as a function from (I_1, I_2, ..., I_n) to integers, it
787+
// must be injective. To guarantee it, the above calculation must not
788+
// overflow. Since we have already checked that 0 <= I_k < S_k for k = 2..n,
789+
// the minimum and maximum values occur in the following cases:
790+
//
791+
// Min = [I_1][0]...[0] = S_2 * ... * S_n * I_1
792+
// Max = [I_1][S_2-1]...[S_n-1]
793+
// = (S_2 * ... * S_n) * I_1 +
794+
// (S_2 * ... * S_{n-1}) * (S_2 - 1) +
795+
// ... +
796+
// (S_n - 1)
797+
// = (S_2 * ... * S_n) * I_1 +
798+
// (S_2 * ... * S_n) - 1 (can be proven by induction)
799+
// = Min + (S_2 * ... * S_n) - 1
800+
//
801+
// NOTE: I_1 can be negative, so Min is not just 0.
802+
const SCEV *Prod = SE.getOne(Sizes[0]->getType());
803+
for (const SCEV *Size : Sizes) {
804+
Prod = MulOverflow(Prod, Size);
805+
if (!Prod)
806+
return false;
807+
}
808+
const SCEV *Min = MulOverflow(Prod, Subscripts[0]);
809+
if (!Min)
810+
return false;
811+
812+
// We have already checked that Min and Prod don't overflow, so it's enough
813+
// to check whether Min + Prod - 1 doesn't overflow.
814+
const SCEV *MaxPlusOne = AddOverflow(Min, Prod);
815+
if (!MaxPlusOne)
816+
return false;
817+
if (!SE.willNotOverflow(Instruction::Sub, /*IsSigned=*/true, MaxPlusOne,
818+
SE.getOne(MaxPlusOne->getType())))
819+
return false;
820+
758821
return true;
759822
}
760823

llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ define void @mat_mul(ptr %C, ptr %A, ptr %B, i64 %N) !kernel_arg_addr_space !2 !
1111
; CHECK-NEXT: Base offset: %A
1212
; CHECK-NEXT: ArrayDecl[UnknownSize][%N] with elements of 4 bytes.
1313
; CHECK-NEXT: ArrayRef[%call][{0,+,1}<nuw><nsw><%for.inc>]
14-
; CHECK-NEXT: Delinearization validation: Succeeded
14+
; CHECK-NEXT: Delinearization validation: Failed
1515
; CHECK-EMPTY:
1616
; CHECK-NEXT: Inst: %tmp5 = load float, ptr %arrayidx4, align 4
1717
; CHECK-NEXT: AccessFunction: {(4 * %call1),+,(4 * %N)}<%for.inc>

llvm/test/Analysis/Delinearization/multidim_only_ivs_2d.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ define void @foo(i64 %n, i64 %m, ptr %A) {
1616
; CHECK-NEXT: Base offset: %A
1717
; CHECK-NEXT: ArrayDecl[UnknownSize][%m] with elements of 8 bytes.
1818
; CHECK-NEXT: ArrayRef[{0,+,1}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%for.j>]
19-
; CHECK-NEXT: Delinearization validation: Succeeded
19+
; CHECK-NEXT: Delinearization validation: Failed
2020
; CHECK-EMPTY:
2121
; CHECK-NEXT: Inst: store double %val, ptr %arrayidx, align 8
2222
; CHECK-NEXT: AccessFunction: {{\{\{}}0,+,(8 * %m)}<%for.i>,+,8}<%for.j>
2323
; CHECK-NEXT: Base offset: %A
2424
; CHECK-NEXT: ArrayDecl[UnknownSize][%m] with elements of 8 bytes.
2525
; CHECK-NEXT: ArrayRef[{0,+,1}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%for.j>]
26-
; CHECK-NEXT: Delinearization validation: Succeeded
26+
; CHECK-NEXT: Delinearization validation: Failed
2727
;
2828
entry:
2929
br label %for.i

llvm/test/Analysis/Delinearization/multidim_only_ivs_3d.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ define void @foo(i64 %n, i64 %m, i64 %o, ptr %A) {
1616
; CHECK-NEXT: Base offset: %A
1717
; CHECK-NEXT: ArrayDecl[UnknownSize][%m][%o] with elements of 8 bytes.
1818
; CHECK-NEXT: ArrayRef[{0,+,1}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%for.j>][{0,+,1}<nuw><nsw><%for.k>]
19-
; CHECK-NEXT: Delinearization validation: Succeeded
19+
; CHECK-NEXT: Delinearization validation: Failed
2020
;
2121
entry:
2222
br label %for.i

llvm/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ define void @foo(i64 %n, i64 %m, ptr %A) {
1919
; CHECK-NEXT: Base offset: %A
2020
; CHECK-NEXT: ArrayDecl[UnknownSize][%m] with elements of 8 bytes.
2121
; CHECK-NEXT: ArrayRef[{0,+,1}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%for.j>]
22-
; CHECK-NEXT: Delinearization validation: Succeeded
22+
; CHECK-NEXT: Delinearization validation: Failed
2323
; CHECK-EMPTY:
2424
; CHECK-NEXT: Inst: store double 1.000000e+00, ptr %arrayidx1, align 8
2525
; CHECK-NEXT: AccessFunction: {{\{\{}}0,+,8}<%for.i>,+,(8 * %n)}<%for.j>
2626
; CHECK-NEXT: Base offset: %A
2727
; CHECK-NEXT: ArrayDecl[UnknownSize][%n] with elements of 8 bytes.
2828
; CHECK-NEXT: ArrayRef[{0,+,1}<nuw><nsw><%for.j>][{0,+,1}<nuw><nsw><%for.i>]
29-
; CHECK-NEXT: Delinearization validation: Succeeded
29+
; CHECK-NEXT: Delinearization validation: Failed
3030
;
3131
entry:
3232
br label %for.i

llvm/test/Analysis/Delinearization/validation_large_size.ll

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
22
; RUN: opt < %s -passes='print<delinearization>' --delinearize-use-fixed-size-array-heuristic -disable-output 2>&1 | FileCheck %s
33

4-
; FIXME: As for array accesses, the following property should hold (without
4+
; As for array accesses, the following property should hold (without
55
; out-of-bound accesses):
66
;
77
; &A[I_1][I_2]...[I_n] == &A[J_1][J_2]...[J_n] iff
88
; (I_1, I_2, ..., I_n) == (J_1, J_2, ..., J_n)
99
;
10-
; Currently, delinearization doesn't guarantee this property, especially when
11-
; the inferred array size is very large so that the product of dimensions may
12-
; overflow. The delinearization validation should consider such cases as
13-
; invalid.
10+
; This property may not hold if the inferred array size is very large and the
11+
; offset calculation can overflow. The delinearization validation should
12+
; consider such cases as invalid.
1413

1514
; for (i = 0; i < (1ULL << 60); i++)
1615
; for (j = 0; j < 256; j++)
@@ -27,7 +26,7 @@ define void @large_size_fixed(ptr %A) {
2726
; CHECK-NEXT: Base offset: %A
2827
; CHECK-NEXT: ArrayDecl[UnknownSize][256] with elements of 1 bytes.
2928
; CHECK-NEXT: ArrayRef[{0,+,1}<nuw><nsw><%for.i.header>][{0,+,1}<nuw><nsw><%for.j>]
30-
; CHECK-NEXT: Delinearization validation: Succeeded
29+
; CHECK-NEXT: Delinearization validation: Failed
3130
;
3231
entry:
3332
br label %for.i.header
@@ -79,7 +78,7 @@ define void @large_size_parametric(i64 %n, i64 %m, i64 %o, ptr %A) {
7978
; CHECK-NEXT: Base offset: %A
8079
; CHECK-NEXT: ArrayDecl[UnknownSize][%m][%o] with elements of 1 bytes.
8180
; CHECK-NEXT: ArrayRef[{0,+,1}<nuw><nsw><%for.i.header>][{0,+,1}<nuw><nsw><%for.j.header>][{0,+,1}<nuw><nsw><%for.k.header>]
82-
; CHECK-NEXT: Delinearization validation: Succeeded
81+
; CHECK-NEXT: Delinearization validation: Failed
8382
;
8483
entry:
8584
%guard.i = icmp sgt i64 %n, 0
@@ -138,3 +137,44 @@ for.i.latch:
138137
exit:
139138
ret void
140139
}
140+
141+
; for (i = 0; i < (1 << 54); i++)
142+
; for (j = 0; j < 256; j++)
143+
; A[i*256 + j] = 0;
144+
;
145+
; We also need to consider the element size when validation.
146+
;
147+
define void @elementsize_cause_ovfl(ptr %A) {
148+
; CHECK-LABEL: 'elementsize_cause_ovfl'
149+
; CHECK-NEXT: Inst: store i64 0, ptr %gep, align 4
150+
; CHECK-NEXT: AccessFunction: {{\{\{}}0,+,2048}<%for.i.header>,+,8}<%for.j>
151+
; CHECK-NEXT: Base offset: %A
152+
; CHECK-NEXT: ArrayDecl[UnknownSize][256] with elements of 8 bytes.
153+
; CHECK-NEXT: ArrayRef[{0,+,1}<nuw><nsw><%for.i.header>][{0,+,1}<nuw><nsw><%for.j>]
154+
; CHECK-NEXT: Delinearization validation: Failed
155+
;
156+
entry:
157+
br label %for.i.header
158+
159+
for.i.header:
160+
%i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.latch ]
161+
%i.mul = mul i64 %i, 256
162+
br label %for.j
163+
164+
for.j:
165+
%j = phi i64 [ 0, %for.i.header ], [ %j.inc, %for.j ]
166+
%offset = add i64 %i.mul, %j
167+
%gep = getelementptr i64, ptr %A, i64 %offset
168+
store i64 0, ptr %gep
169+
%j.inc = add i64 %j, 1
170+
%ec.j = icmp eq i64 %j.inc, 256
171+
br i1 %ec.j, label %for.i.latch, label %for.j
172+
173+
for.i.latch:
174+
%i.inc = add i64 %i, 1
175+
%ec.i = icmp eq i64 %i.inc, 18014398509481984
176+
br i1 %ec.i, label %exit, label %for.i.header
177+
178+
exit:
179+
ret void
180+
}

llvm/test/Analysis/DependenceAnalysis/DADelin.ll

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ target triple = "thumbv8m.main-arm-none-eabi"
1313
define void @t1(i32 %n, i32 %m, i32 %o, ptr nocapture %A) {
1414
; CHECK-LABEL: 't1'
1515
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx, align 4
16-
; CHECK-NEXT: da analyze - none!
16+
; CHECK-NEXT: da analyze - input [* * *]!
1717
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: store i32 %add12, ptr %arrayidx, align 4
18-
; CHECK-NEXT: da analyze - consistent anti [0 0 0|<]!
18+
; CHECK-NEXT: da analyze - anti [* * *|<]!
1919
; CHECK-NEXT: Src: store i32 %add12, ptr %arrayidx, align 4 --> Dst: store i32 %add12, ptr %arrayidx, align 4
20-
; CHECK-NEXT: da analyze - none!
20+
; CHECK-NEXT: da analyze - output [* * *]!
2121
;
2222
entry:
2323
%cmp49 = icmp sgt i32 %n, 0
@@ -78,7 +78,7 @@ for.cond.cleanup: ; preds = %for.cond.cleanup3,
7878
define void @t2(i32 %n, i32 %m, i32 %o, ptr nocapture %A) {
7979
; CHECK-LABEL: 't2'
8080
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx, align 4
81-
; CHECK-NEXT: da analyze - none!
81+
; CHECK-NEXT: da analyze - input [* * *]!
8282
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
8383
; CHECK-NEXT: da analyze - anti [* * *|<]!
8484
; CHECK-NEXT: Src: store i32 %add12, ptr %arrayidx2, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
@@ -145,7 +145,7 @@ for.cond.cleanup: ; preds = %for.cond.cleanup3,
145145
define void @t3(i32 %n, i32 %m, i32 %o, ptr nocapture %A) {
146146
; CHECK-LABEL: 't3'
147147
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx, align 4
148-
; CHECK-NEXT: da analyze - none!
148+
; CHECK-NEXT: da analyze - input [* * *]!
149149
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
150150
; CHECK-NEXT: da analyze - anti [* * *|<]!
151151
; CHECK-NEXT: Src: store i32 %add12, ptr %arrayidx2, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
@@ -212,7 +212,7 @@ for.cond.cleanup: ; preds = %for.cond.cleanup3,
212212
define void @t4(i32 %n, i32 %m, i32 %o, ptr nocapture %A) {
213213
; CHECK-LABEL: 't4'
214214
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx, align 4
215-
; CHECK-NEXT: da analyze - none!
215+
; CHECK-NEXT: da analyze - input [* * *]!
216216
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
217217
; CHECK-NEXT: da analyze - anti [* * *|<]!
218218
; CHECK-NEXT: Src: store i32 %add12, ptr %arrayidx2, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
@@ -279,7 +279,7 @@ for.cond.cleanup: ; preds = %for.cond.cleanup3,
279279
define void @t5(i32 %n, i32 %m, i32 %o, ptr nocapture %A) {
280280
; CHECK-LABEL: 't5'
281281
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx, align 4
282-
; CHECK-NEXT: da analyze - none!
282+
; CHECK-NEXT: da analyze - input [* * *]!
283283
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
284284
; CHECK-NEXT: da analyze - anti [* * *|<]!
285285
; CHECK-NEXT: Src: store i32 %add12, ptr %arrayidx2, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
@@ -346,11 +346,11 @@ for.cond.cleanup: ; preds = %for.cond.cleanup3,
346346
define void @t6(i32 %n, i32 %m, i32 %o, ptr nocapture %A) {
347347
; CHECK-LABEL: 't6'
348348
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx, align 4
349-
; CHECK-NEXT: da analyze - none!
349+
; CHECK-NEXT: da analyze - input [* * *]!
350350
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
351-
; CHECK-NEXT: da analyze - consistent anti [-1 0 0]!
351+
; CHECK-NEXT: da analyze - anti [* * *|<]!
352352
; CHECK-NEXT: Src: store i32 %add12, ptr %arrayidx2, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
353-
; CHECK-NEXT: da analyze - none!
353+
; CHECK-NEXT: da analyze - output [* * *]!
354354
;
355355
entry:
356356
%cmp49 = icmp sgt i32 %n, 0
@@ -414,11 +414,11 @@ for.cond.cleanup: ; preds = %for.cond.cleanup3,
414414
define void @t7(i32 %n, i32 %m, i32 %o, ptr nocapture %A) {
415415
; CHECK-LABEL: 't7'
416416
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx, align 4
417-
; CHECK-NEXT: da analyze - none!
417+
; CHECK-NEXT: da analyze - input [* * *]!
418418
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
419-
; CHECK-NEXT: da analyze - consistent anti [1 0 0]!
419+
; CHECK-NEXT: da analyze - anti [* * *|<]!
420420
; CHECK-NEXT: Src: store i32 %add12, ptr %arrayidx2, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
421-
; CHECK-NEXT: da analyze - none!
421+
; CHECK-NEXT: da analyze - output [* * *]!
422422
;
423423
entry:
424424
%cmp49 = icmp sgt i32 %n, 0
@@ -482,11 +482,11 @@ for.cond.cleanup: ; preds = %for.cond.cleanup3,
482482
define void @t8(i32 %n, i32 %m, i32 %o, ptr nocapture %A) {
483483
; CHECK-LABEL: 't8'
484484
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx, align 4
485-
; CHECK-NEXT: da analyze - none!
485+
; CHECK-NEXT: da analyze - input [* * *]!
486486
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
487-
; CHECK-NEXT: da analyze - consistent anti [0 0 1]!
487+
; CHECK-NEXT: da analyze - anti [* * *|<]!
488488
; CHECK-NEXT: Src: store i32 %add12, ptr %arrayidx2, align 4 --> Dst: store i32 %add12, ptr %arrayidx2, align 4
489-
; CHECK-NEXT: da analyze - none!
489+
; CHECK-NEXT: da analyze - output [* * *]!
490490
;
491491
entry:
492492
%cmp49 = icmp sgt i32 %n, 0

llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ define void @linearized_accesses(i64 %n, i64 %m, i64 %o, ptr %A) {
9393
; CHECK-NEXT: Src: store i32 1, ptr %idx0, align 4 --> Dst: store i32 1, ptr %idx1, align 4
9494
; CHECK-NEXT: da analyze - output [* * *|<]!
9595
; CHECK-NEXT: Src: store i32 1, ptr %idx1, align 4 --> Dst: store i32 1, ptr %idx1, align 4
96-
; CHECK-NEXT: da analyze - none!
96+
; CHECK-NEXT: da analyze - output [* * *]!
9797
;
9898
entry:
9999
br label %for.i

llvm/test/Analysis/DependenceAnalysis/StrongSIV.ll

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,9 +536,13 @@ for.end: ; preds = %for.body
536536
;; A[i] = 0;
537537

538538
define void @strong11(ptr %A) nounwind uwtable ssp {
539-
; CHECK-LABEL: 'strong11'
540-
; CHECK-NEXT: Src: store i32 0, ptr %arrayidx, align 4 --> Dst: store i32 0, ptr %arrayidx, align 4
541-
; CHECK-NEXT: da analyze - consistent output [0 S]!
539+
; CHECK-ALL-LABEL: 'strong11'
540+
; CHECK-ALL-NEXT: Src: store i32 0, ptr %arrayidx, align 4 --> Dst: store i32 0, ptr %arrayidx, align 4
541+
; CHECK-ALL-NEXT: da analyze - none!
542+
;
543+
; CHECK-STRONG-SIV-LABEL: 'strong11'
544+
; CHECK-STRONG-SIV-NEXT: Src: store i32 0, ptr %arrayidx, align 4 --> Dst: store i32 0, ptr %arrayidx, align 4
545+
; CHECK-STRONG-SIV-NEXT: da analyze - consistent output [0 S]!
542546
;
543547
entry:
544548
br label %for.cond1.preheader

llvm/test/Transforms/LICM/lnicm.ll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
; RUN: opt -aa-pipeline=basic-aa -passes='loop-mssa(lnicm),loop(loop-interchange)' -cache-line-size=64 -S %s | FileCheck %s --check-prefixes LNICM
44
; RUN: opt -aa-pipeline=basic-aa -passes='loop-mssa(licm),loop(loop-interchange)' -cache-line-size=64 -S %s | FileCheck %s --check-prefixes LICM
55

6+
; XFAIL: *
7+
; Loop interchange currently fails due to a failure in dependence analysis.
8+
69
; This test represents the following function:
710
; void test(int n, int m, int x[m][n], int y[n], int *z) {
811
; for (int k = 0; k < n; k++) {

0 commit comments

Comments
 (0)