Skip to content

Commit e575d9d

Browse files
committed
[DA] use NSW arithmetic
This patch fixes #51512 DA uses SCEVs to represent linear constraints on memory accesses. addToCoefficient is only called from the "Constraint Propagation engine": https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/DependenceAnalysis.cpp#L3877 The propagation engine works on MIV subscripts. MIV subscripts are pairs of *linear* memory accesses that vary in multiple loops. At this point all memory accesses are linear, non-linear have been filtered out. When addToCoefficient creates an AddRec with flags SCEV::FlagAnyWrap, classifyPair returns llvm::DependenceInfo::Subscript::NonLinear. https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/DependenceAnalysis.cpp#L3882 Having a non-linear effect this late in the dependence test is surprising, and the test fails with llvm_unreachable("bad subscript classification"). Instead of building non-linear functions, this patch modifies the flags to SCEV::FlagNSW that has the meaning of linear functions that do not wrap around.
1 parent 46c4845 commit e575d9d

File tree

2 files changed

+52
-6
lines changed

2 files changed

+52
-6
lines changed

llvm/lib/Analysis/DependenceAnalysis.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3115,15 +3115,17 @@ const SCEV *DependenceInfo::zeroCoefficient(const SCEV *Expr,
31153115
// coefficient corresponding to the specified TargetLoop.
31163116
// For example, given a*i + b*j + c*k, adding 1 to the coefficient
31173117
// corresponding to the j loop would yield a*i + (b+1)*j + c*k.
3118+
3119+
// When Expr is invariant in TargetLoop, i.e., the stride in TargetLoop is 0,
3120+
// addToCoefficient returns an AddRec {Expr, +, Value}_TargetLoop.
3121+
// NoWrapFlags is set to FlagNSW for the evolution function to be linear.
31183122
const SCEV *DependenceInfo::addToCoefficient(const SCEV *Expr,
31193123
const Loop *TargetLoop,
31203124
const SCEV *Value) const {
31213125
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Expr);
3122-
if (!AddRec) // create a new addRec
3123-
return SE->getAddRecExpr(Expr,
3124-
Value,
3125-
TargetLoop,
3126-
SCEV::FlagAnyWrap); // Worst case, with no info.
3126+
if (!AddRec)
3127+
return SE->getAddRecExpr(Expr, Value, TargetLoop, SCEV::FlagNSW);
3128+
31273129
if (AddRec->getLoop() == TargetLoop) {
31283130
const SCEV *Sum = SE->getAddExpr(AddRec->getStepRecurrence(*SE), Value);
31293131
if (Sum->isZero())
@@ -3134,7 +3136,7 @@ const SCEV *DependenceInfo::addToCoefficient(const SCEV *Expr,
31343136
AddRec->getNoWrapFlags());
31353137
}
31363138
if (SE->isLoopInvariant(AddRec, TargetLoop))
3137-
return SE->getAddRecExpr(AddRec, Value, TargetLoop, SCEV::FlagAnyWrap);
3139+
return SE->getAddRecExpr(AddRec, Value, TargetLoop, SCEV::FlagNSW);
31383140
return SE->getAddRecExpr(
31393141
addToCoefficient(AddRec->getStart(), TargetLoop, Value),
31403142
AddRec->getStepRecurrence(*SE), AddRec->getLoop(),
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt < %s -disable-output "-passes=print<da>" -aa-pipeline=basic-aa 2>&1 \
3+
; RUN: | FileCheck %s
4+
5+
; Check that the testcase does not crash the compiler.
6+
; See https://github.com/llvm/llvm-project/issues/51512 for details.
7+
8+
define void @foo() {
9+
; CHECK-LABEL: 'foo'
10+
; CHECK-NEXT: Src: store i32 42, ptr %getelementptr, align 1 --> Dst: store i32 42, ptr %getelementptr, align 1
11+
; CHECK-NEXT: da analyze - consistent output [0 S]!
12+
; CHECK-NEXT: Src: store i32 42, ptr %getelementptr, align 1 --> Dst: store i32 0, ptr %getelementptr5, align 1
13+
; CHECK-NEXT: da analyze - output [0 *|<]!
14+
; CHECK-NEXT: Src: store i32 0, ptr %getelementptr5, align 1 --> Dst: store i32 0, ptr %getelementptr5, align 1
15+
; CHECK-NEXT: da analyze - none!
16+
;
17+
bb:
18+
%alloca = alloca [2 x [5 x i32]], align 1
19+
br label %bb1
20+
21+
bb1: ; preds = %bb7, %bb
22+
%phi = phi i32 [ 0, %bb ], [ %add8, %bb7 ]
23+
%trunc = trunc i32 %phi to i16
24+
%add = add i16 %trunc, 3
25+
%getelementptr = getelementptr inbounds [2 x [5 x i32]], ptr %alloca, i16 0, i16 %trunc, i16 %add
26+
br label %bb2
27+
28+
bb2: ; preds = %bb2, %bb1
29+
%phi3 = phi i32 [ 0, %bb1 ], [ %add6, %bb2 ]
30+
store i32 42, ptr %getelementptr, align 1
31+
%trunc4 = trunc i32 %phi3 to i16
32+
%getelementptr5 = getelementptr inbounds [2 x [5 x i32]], ptr %alloca, i16 0, i16 %trunc4, i16 %add
33+
store i32 0, ptr %getelementptr5, align 1
34+
%add6 = add nuw nsw i32 %phi3, 1
35+
br i1 false, label %bb2, label %bb7
36+
37+
bb7: ; preds = %bb2
38+
%add8 = add nuw nsw i32 %phi, 1
39+
%icmp = icmp eq i32 %phi, 0
40+
br i1 %icmp, label %bb1, label %bb9
41+
42+
bb9: ; preds = %bb7
43+
ret void
44+
}

0 commit comments

Comments
 (0)