[llvm] 9383246 - [DA] Fix zero coeff bug in Strong SIV test with runtime assumptions (#149991) (#155037)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 3 09:20:00 PST 2025
Author: Sebastian Pop
Date: 2025-12-03T11:19:56-06:00
New Revision: 93832466cc40c142eb39d96876f98b49927c255b
URL: https://github.com/llvm/llvm-project/commit/93832466cc40c142eb39d96876f98b49927c255b
DIFF: https://github.com/llvm/llvm-project/commit/93832466cc40c142eb39d96876f98b49927c255b.diff
LOG: [DA] Fix zero coeff bug in Strong SIV test with runtime assumptions (#149991) (#155037)
Fix GitHub issue #149991 where Strong SIV test incorrectly concludes
'none!' for symbolic coefficients that could be zero, leading to 0/0
undef behavior.
The Strong SIV test was incorrectly concluding "no dependence" when the
coefficient is symbolic and the delta (difference between source and
destination) is zero.
When delta=0, the Strong SIV test divides delta/coeff to get the
distance.
The bug occurs when coeff is an unknown symbolic value: if coeff=0 at
runtime,
then 0/0 is undefined and all iterations access the same memory
location,
creating a true dependence that was being missed.
Added:
llvm/test/Analysis/DependenceAnalysis/zero-coefficient.ll
Modified:
llvm/include/llvm/Analysis/DependenceAnalysis.h
llvm/include/llvm/Analysis/ScalarEvolution.h
llvm/lib/Analysis/DependenceAnalysis.cpp
llvm/test/Analysis/DependenceAnalysis/DADelin.ll
llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll
llvm/test/Analysis/DependenceAnalysis/MIVCheckConst.ll
llvm/test/Analysis/DependenceAnalysis/StrongSIV.ll
llvm/test/Analysis/DependenceAnalysis/SymbolicSIV.ll
llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll
llvm/test/Analysis/DependenceAnalysis/WeakZeroDstSIV.ll
llvm/test/Analysis/DependenceAnalysis/WeakZeroSrcSIV.ll
llvm/test/Analysis/DependenceAnalysis/becount-couldnotcompute.ll
llvm/test/Analysis/DependenceAnalysis/compute-absolute-value.ll
llvm/test/Analysis/DependenceAnalysis/gcd-miv-overflow.ll
llvm/test/Analysis/DependenceAnalysis/monotonicity-cast.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/DependenceAnalysis.h b/llvm/include/llvm/Analysis/DependenceAnalysis.h
index ad46d2f1466cf..6dec24fc9f104 100644
--- a/llvm/include/llvm/Analysis/DependenceAnalysis.h
+++ b/llvm/include/llvm/Analysis/DependenceAnalysis.h
@@ -543,7 +543,7 @@ class DependenceInfo {
/// If the dependence isn't proven to exist,
/// marks the Result as inconsistent.
bool testSIV(const SCEV *Src, const SCEV *Dst, unsigned &Level,
- FullDependence &Result) const;
+ FullDependence &Result, bool UnderRuntimeAssumptions);
/// testRDIV - Tests the RDIV subscript pair (Src and Dst) for dependence.
/// Things of the form [c1 + a1*i] and [c2 + a2*j]
@@ -573,7 +573,7 @@ class DependenceInfo {
bool strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
const SCEV *DstConst, const Loop *CurrentSrcLoop,
const Loop *CurrentDstLoop, unsigned Level,
- FullDependence &Result) const;
+ FullDependence &Result, bool UnderRuntimeAssumptions);
/// weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair
/// (Src and Dst) for dependence.
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 6e086b55e9e99..9ce23ab344668 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -427,6 +427,15 @@ class LLVM_ABI SCEVUnionPredicate final : public SCEVPredicate {
ArrayRef<const SCEVPredicate *> getPredicates() const { return Preds; }
+ /// Returns a new SCEVUnionPredicate that is the union of this predicate
+ /// and the given predicate \p N.
+ SCEVUnionPredicate getUnionWith(const SCEVPredicate *N,
+ ScalarEvolution &SE) const {
+ SCEVUnionPredicate Result(Preds, SE);
+ Result.add(N, SE);
+ return Result;
+ }
+
/// Implementation of the SCEVPredicate interface
bool isAlwaysTrue() const override;
bool implies(const SCEVPredicate *N, ScalarEvolution &SE) const override;
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index 7e908a3b73868..fe07b7edb6713 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1296,7 +1296,8 @@ bool DependenceInfo::testZIV(const SCEV *Src, const SCEV *Dst,
bool DependenceInfo::strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
const SCEV *DstConst, const Loop *CurSrcLoop,
const Loop *CurDstLoop, unsigned Level,
- FullDependence &Result) const {
+ FullDependence &Result,
+ bool UnderRuntimeAssumptions) {
if (!isDependenceTestEnabled(DependenceTestType::StrongSIV))
return false;
@@ -1368,7 +1369,29 @@ bool DependenceInfo::strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
Result.DV[Level].Direction &= Dependence::DVEntry::EQ;
++StrongSIVsuccesses;
} else if (Delta->isZero()) {
- // since 0/X == 0
+ // Check if coefficient could be zero. If so, 0/0 is undefined and we
+ // cannot conclude that only same-iteration dependencies exist.
+ // When coeff=0, all iterations access the same location.
+ if (SE->isKnownNonZero(Coeff)) {
+ LLVM_DEBUG(
+ dbgs() << "\t Coefficient proven non-zero by SCEV analysis\n");
+ } else {
+ // Cannot prove at compile time, would need runtime assumption.
+ if (UnderRuntimeAssumptions) {
+ const SCEVPredicate *Pred = SE->getComparePredicate(
+ ICmpInst::ICMP_NE, Coeff, SE->getZero(Coeff->getType()));
+ Result.Assumptions = Result.Assumptions.getUnionWith(Pred, *SE);
+ LLVM_DEBUG(dbgs() << "\t Added runtime assumption: " << *Coeff
+ << " != 0\n");
+ } else {
+ // Cannot add runtime assumptions, this test cannot handle this case.
+ // Let more complex tests try.
+ LLVM_DEBUG(dbgs() << "\t Would need runtime assumption " << *Coeff
+ << " != 0, but not allowed. Failing this test.\n");
+ return false;
+ }
+ }
+ // Since 0/X == 0 (where X is known non-zero or assumed non-zero).
Result.DV[Level].Distance = Delta;
Result.DV[Level].Direction &= Dependence::DVEntry::EQ;
++StrongSIVsuccesses;
@@ -2331,7 +2354,8 @@ bool DependenceInfo::symbolicRDIVtest(const SCEV *A1, const SCEV *A2,
//
// Return true if dependence disproved.
bool DependenceInfo::testSIV(const SCEV *Src, const SCEV *Dst, unsigned &Level,
- FullDependence &Result) const {
+ FullDependence &Result,
+ bool UnderRuntimeAssumptions) {
LLVM_DEBUG(dbgs() << " src = " << *Src << "\n");
LLVM_DEBUG(dbgs() << " dst = " << *Dst << "\n");
const SCEVAddRecExpr *SrcAddRec = dyn_cast<SCEVAddRecExpr>(Src);
@@ -2349,8 +2373,9 @@ bool DependenceInfo::testSIV(const SCEV *Src, const SCEV *Dst, unsigned &Level,
Level = mapSrcLoop(CurSrcLoop);
bool disproven;
if (SrcCoeff == DstCoeff)
- disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
- CurDstLoop, Level, Result);
+ disproven =
+ strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop, CurDstLoop,
+ Level, Result, UnderRuntimeAssumptions);
else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
CurDstLoop, Level, Result);
@@ -3463,11 +3488,10 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
SCEVUnionPredicate(Assume, *SE));
}
- if (!Assume.empty() && !UnderRuntimeAssumptions) {
- // Runtime assumptions needed but not allowed.
+ // Runtime assumptions needed but not allowed.
+ if (!Assume.empty() && !UnderRuntimeAssumptions)
return std::make_unique<Dependence>(Src, Dst,
SCEVUnionPredicate(Assume, *SE));
- }
unsigned Pairs = 1;
SmallVector<Subscript, 2> Pair(Pairs);
@@ -3567,7 +3591,8 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
case Subscript::SIV: {
LLVM_DEBUG(dbgs() << ", SIV\n");
unsigned Level;
- if (testSIV(Pair[SI].Src, Pair[SI].Dst, Level, Result))
+ if (testSIV(Pair[SI].Src, Pair[SI].Dst, Level, Result,
+ UnderRuntimeAssumptions))
return nullptr;
break;
}
@@ -3648,6 +3673,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
} else {
// On the other hand, if all directions are equal and there's no
// loop-independent dependence possible, then no dependence exists.
+ // However, if there are runtime assumptions, we must return the result.
bool AllEqual = true;
for (unsigned II = 1; II <= CommonLevels; ++II) {
if (Result.getDirection(II) != Dependence::DVEntry::EQ) {
@@ -3655,7 +3681,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
break;
}
}
- if (AllEqual)
+ if (AllEqual && Result.Assumptions.getPredicates().empty())
return nullptr;
}
diff --git a/llvm/test/Analysis/DependenceAnalysis/DADelin.ll b/llvm/test/Analysis/DependenceAnalysis/DADelin.ll
index 130b9930cfdf5..429e37de0a453 100644
--- a/llvm/test/Analysis/DependenceAnalysis/DADelin.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/DADelin.ll
@@ -646,11 +646,15 @@ exit:
define void @coeff_may_negative(ptr %a, i32 %k) {
; CHECK-LABEL: 'coeff_may_negative'
; CHECK-NEXT: Src: store i8 42, ptr %idx.0, align 1 --> Dst: store i8 42, ptr %idx.0, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: %k ne) 0
; CHECK-NEXT: Src: store i8 42, ptr %idx.0, align 1 --> Dst: store i8 42, ptr %idx.1, align 1
; CHECK-NEXT: da analyze - output [*|<]!
; CHECK-NEXT: Src: store i8 42, ptr %idx.1, align 1 --> Dst: store i8 42, ptr %idx.1, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: %k ne) 0
;
entry:
br label %loop
@@ -685,11 +689,15 @@ exit:
define void @coeff_positive(ptr %a, i32 %k) {
; CHECK-LABEL: 'coeff_positive'
; CHECK-NEXT: Src: store i8 42, ptr %idx.0, align 1 --> Dst: store i8 42, ptr %idx.0, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: %k ne) 0
; CHECK-NEXT: Src: store i8 42, ptr %idx.0, align 1 --> Dst: store i8 42, ptr %idx.1, align 1
; CHECK-NEXT: da analyze - output [*|<]!
; CHECK-NEXT: Src: store i8 42, ptr %idx.1, align 1 --> Dst: store i8 42, ptr %idx.1, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: %k ne) 0
;
entry:
br label %loop
diff --git a/llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll b/llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll
index fd634c8b97e24..3360e603eb406 100644
--- a/llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll
@@ -27,7 +27,9 @@ entry:
define i32 @alias_with_parametric_offset(ptr nocapture %A, i64 %n) {
; CHECK-LABEL: 'alias_with_parametric_offset'
; CHECK-NEXT: Src: store i32 2, ptr %arrayidx, align 1 --> Dst: store i32 2, ptr %arrayidx, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output []!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Equal predicate: (zext i2 (trunc i64 %n to i2) to i64) == 0
; CHECK-NEXT: Src: store i32 2, ptr %arrayidx, align 1 --> Dst: %0 = load i32, ptr %A, align 1
; CHECK-NEXT: da analyze - flow [|<]!
; CHECK-NEXT: Runtime Assumptions:
@@ -45,14 +47,18 @@ entry:
define i32 @alias_with_parametric_expr(ptr nocapture %A, i64 %n, i64 %m) {
; CHECK-LABEL: 'alias_with_parametric_expr'
; CHECK-NEXT: Src: store i32 2, ptr %arrayidx, align 1 --> Dst: store i32 2, ptr %arrayidx, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output []!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Equal predicate: (zext i2 ((trunc i64 %m to i2) + (-2 * (trunc i64 %n to i2))) to i64) == 0
; CHECK-NEXT: Src: store i32 2, ptr %arrayidx, align 1 --> Dst: %0 = load i32, ptr %arrayidx1, align 1
; CHECK-NEXT: da analyze - flow [|<]!
; CHECK-NEXT: Runtime Assumptions:
; CHECK-NEXT: Equal predicate: (zext i2 ((trunc i64 %m to i2) + (-2 * (trunc i64 %n to i2))) to i64) == 0
; CHECK-NEXT: Equal predicate: (zext i2 (-2 + (trunc i64 %m to i2)) to i64) == 0
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 1 --> Dst: %0 = load i32, ptr %arrayidx1, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent input []!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Equal predicate: (zext i2 (-2 + (trunc i64 %m to i2)) to i64) == 0
;
entry:
%mul = mul nsw i64 %n, 10
@@ -69,7 +75,9 @@ entry:
define i32 @gep_i8_vs_i32(ptr nocapture %A, i64 %n, i64 %m) {
; CHECK-LABEL: 'gep_i8_vs_i32'
; CHECK-NEXT: Src: store i32 42, ptr %arrayidx0, align 1 --> Dst: store i32 42, ptr %arrayidx0, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output []!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Equal predicate: (zext i2 (trunc i64 %n to i2) to i64) == 0
; CHECK-NEXT: Src: store i32 42, ptr %arrayidx0, align 1 --> Dst: store i32 42, ptr %arrayidx1, align 4
; CHECK-NEXT: da analyze - output [|<]!
; CHECK-NEXT: Runtime Assumptions:
diff --git a/llvm/test/Analysis/DependenceAnalysis/MIVCheckConst.ll b/llvm/test/Analysis/DependenceAnalysis/MIVCheckConst.ll
index bcf73683e4dab..d91a916d785c2 100644
--- a/llvm/test/Analysis/DependenceAnalysis/MIVCheckConst.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/MIVCheckConst.ll
@@ -43,6 +43,7 @@ define void @test(ptr %A, ptr %B, i1 %arg, i32 %n, i32 %m) align 2 {
; CHECK-NEXT: Runtime Assumptions:
; CHECK-NEXT: Equal predicate: (zext i7 (4 * (trunc i32 %v1 to i7) * (1 + (trunc i32 %n to i7))) to i32) == 0
; CHECK-NEXT: Equal predicate: (8 * (zext i4 (trunc i32 %v1 to i4) to i32))<nuw><nsw> == 0
+; CHECK-NEXT: Compare predicate: (8 * %v1) ne) 0
; CHECK-NEXT: Src: %v27 = load <32 x i32>, ptr %v25, align 256 --> Dst: %v32 = load <32 x i32>, ptr %v30, align 128
; CHECK-NEXT: da analyze - input [* S S|<]!
; CHECK-NEXT: Runtime Assumptions:
diff --git a/llvm/test/Analysis/DependenceAnalysis/StrongSIV.ll b/llvm/test/Analysis/DependenceAnalysis/StrongSIV.ll
index 16e0e7bccaaf5..02fbaf2910c70 100644
--- a/llvm/test/Analysis/DependenceAnalysis/StrongSIV.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/StrongSIV.ll
@@ -492,13 +492,19 @@ for.end: ; preds = %for.end.loopexit, %
define void @strong10(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp {
; CHECK-LABEL: 'strong10'
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (4 * %n) ne) 0
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx3, align 4
; CHECK-NEXT: da analyze - consistent flow [0|<]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (4 * %n) ne) 0
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx3, align 4 --> Dst: %0 = load i32, ptr %arrayidx3, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent input [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (4 * %n) ne) 0
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx3, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.01, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4
diff --git a/llvm/test/Analysis/DependenceAnalysis/SymbolicSIV.ll b/llvm/test/Analysis/DependenceAnalysis/SymbolicSIV.ll
index e43aa0f407b50..a33a10b5e1c2d 100644
--- a/llvm/test/Analysis/DependenceAnalysis/SymbolicSIV.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/SymbolicSIV.ll
@@ -381,13 +381,17 @@ for.end: ; preds = %for.end.loopexit, %
define void @symbolicsiv6(ptr %A, ptr %B, i64 %n, i64 %N, i64 %M) nounwind uwtable ssp {
; CHECK-LABEL: 'symbolicsiv6'
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (16 * %N) ne) 0
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx7, align 4
; CHECK-NEXT: da analyze - flow [*|<]!
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx7, align 4 --> Dst: %0 = load i32, ptr %arrayidx7, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent input [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (16 * %N) ne) 0
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx7, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4
@@ -437,13 +441,17 @@ for.end: ; preds = %for.end.loopexit, %
define void @symbolicsiv7(ptr %A, ptr %B, i64 %n, i64 %N, i64 %M) nounwind uwtable ssp {
; CHECK-LABEL: 'symbolicsiv7'
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (8 * %N) ne) 0
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %1 = load i32, ptr %arrayidx6, align 4
; CHECK-NEXT: da analyze - flow [*|<]!
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: %1 = load i32, ptr %arrayidx6, align 4 --> Dst: %1 = load i32, ptr %arrayidx6, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent input [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (8 * %N) ne) 0
; CHECK-NEXT: Src: %1 = load i32, ptr %arrayidx6, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: store i32 %1, ptr %B.addr.02, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4
diff --git a/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll b/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll
index 906505eef51b9..c7accfd46a4d7 100644
--- a/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll
@@ -14,13 +14,17 @@ target triple = "x86_64-apple-macosx10.6.0"
define void @weakcrossing0(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp {
; CHECK-LABEL: 'weakcrossing0'
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (4 * %n) ne) 0
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx2, align 4
; CHECK-NEXT: da analyze - flow [0|<]!
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx2, align 4 --> Dst: %0 = load i32, ptr %arrayidx2, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent input [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (-4 * %n) ne) 0
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx2, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4
diff --git a/llvm/test/Analysis/DependenceAnalysis/WeakZeroDstSIV.ll b/llvm/test/Analysis/DependenceAnalysis/WeakZeroDstSIV.ll
index 71a5ed62b8e21..f8a045c425029 100644
--- a/llvm/test/Analysis/DependenceAnalysis/WeakZeroDstSIV.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/WeakZeroDstSIV.ll
@@ -90,7 +90,9 @@ for.end: ; preds = %for.body
define void @weakzerodst1(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp {
; CHECK-LABEL: 'weakzerodst1'
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (4 * %n) ne) 0
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx1, align 4
; CHECK-NEXT: da analyze - flow [p<=|<]!
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4
diff --git a/llvm/test/Analysis/DependenceAnalysis/WeakZeroSrcSIV.ll b/llvm/test/Analysis/DependenceAnalysis/WeakZeroSrcSIV.ll
index 2ee1a37775f46..4ed0abd8d98a9 100644
--- a/llvm/test/Analysis/DependenceAnalysis/WeakZeroSrcSIV.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/WeakZeroSrcSIV.ll
@@ -94,7 +94,9 @@ define void @weakzerosrc1(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp {
; CHECK-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: %0 = load i32, ptr %arrayidx1, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent input [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (4 * %n) ne) 0
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4
diff --git a/llvm/test/Analysis/DependenceAnalysis/becount-couldnotcompute.ll b/llvm/test/Analysis/DependenceAnalysis/becount-couldnotcompute.ll
index 49fbad3510ae6..1674badd4d6b9 100644
--- a/llvm/test/Analysis/DependenceAnalysis/becount-couldnotcompute.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/becount-couldnotcompute.ll
@@ -7,7 +7,9 @@
define void @test(i64 %conv, ptr %a) {
; CHECK-LABEL: 'test'
; CHECK-NEXT: Src: %ld = load i32, ptr %arrayidx12, align 4 --> Dst: %ld = load i32, ptr %arrayidx12, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent input [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (4 + (4 * %conv)) ne) 0
;
entry:
%sub = add i64 %conv, 1
diff --git a/llvm/test/Analysis/DependenceAnalysis/compute-absolute-value.ll b/llvm/test/Analysis/DependenceAnalysis/compute-absolute-value.ll
index 783150af2cd13..f3ce956545482 100644
--- a/llvm/test/Analysis/DependenceAnalysis/compute-absolute-value.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/compute-absolute-value.ll
@@ -16,11 +16,15 @@
define void @unknown_sign(ptr %a, i64 %k) {
; CHECK-LABEL: 'unknown_sign'
; CHECK-NEXT: Src: store i8 1, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.0, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (-1 * %k) ne) 0
; CHECK-NEXT: Src: store i8 1, ptr %idx.0, align 1 --> Dst: store i8 2, ptr %idx.1, align 1
; CHECK-NEXT: da analyze - output [*|<]!
; CHECK-NEXT: Src: store i8 2, ptr %idx.1, align 1 --> Dst: store i8 2, ptr %idx.1, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (-1 * %k) ne) 0
;
entry:
%k.neg = sub nsw i64 0, %k
diff --git a/llvm/test/Analysis/DependenceAnalysis/gcd-miv-overflow.ll b/llvm/test/Analysis/DependenceAnalysis/gcd-miv-overflow.ll
index 569bba077593a..ff8f32b9c8276 100644
--- a/llvm/test/Analysis/DependenceAnalysis/gcd-miv-overflow.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/gcd-miv-overflow.ll
@@ -24,7 +24,9 @@
define void @gcdmiv_coef_ovfl(ptr %A, i64 %m) {
; CHECK-ALL-LABEL: 'gcdmiv_coef_ovfl'
; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
-; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: da analyze - consistent output [0]!
+; CHECK-ALL-NEXT: Runtime Assumptions:
+; CHECK-ALL-NEXT: Compare predicate: (3 * %m) ne) 0
; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
; CHECK-ALL-NEXT: da analyze - output [*|<]!
; CHECK-ALL-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
diff --git a/llvm/test/Analysis/DependenceAnalysis/monotonicity-cast.ll b/llvm/test/Analysis/DependenceAnalysis/monotonicity-cast.ll
index e43d00d0bf651..966e4462fb887 100644
--- a/llvm/test/Analysis/DependenceAnalysis/monotonicity-cast.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/monotonicity-cast.ll
@@ -14,7 +14,9 @@ define void @sext_nsw(ptr %a, i8 %start, i8 %step) {
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: (sext i8 %step to i64) ne) 0
;
entry:
br label %loop
diff --git a/llvm/test/Analysis/DependenceAnalysis/zero-coefficient.ll b/llvm/test/Analysis/DependenceAnalysis/zero-coefficient.ll
new file mode 100644
index 0000000000000..55f0ecc123e3a
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/zero-coefficient.ll
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -disable-output "-passes=print<da>" -aa-pipeline=basic-aa 2>&1 \
+; RUN: | FileCheck %s
+
+; Test case for bug #149991 where Strong SIV test incorrectly concludes "no dependence"
+; when the coefficient is symbolic (unknown at compile time) and delta is zero.
+;
+; In this case, the array access is A[k*i] with both src and dst at the same
+; location in the same iteration. If k=0, then all iterations access the same
+; element, meaning there IS a dependence between
diff erent iterations.
+; The Strong SIV test should add a runtime assumption that k != 0.
+
+define void @test_zero_coefficient(ptr noalias %A, i64 %k) {
+; CHECK-LABEL: 'test_zero_coefficient'
+; CHECK-NEXT: Src: store i8 42, ptr %idx, align 1 --> Dst: store i8 42, ptr %idx, align 1
+; CHECK-NEXT: da analyze - consistent output [0]!
+; CHECK-NEXT: Runtime Assumptions:
+; CHECK-NEXT: Compare predicate: %k ne) 0
+;
+entry:
+ br label %loop
+
+loop:
+ %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+ %off = mul nsw i64 %i, %k
+ %idx = getelementptr inbounds i8, ptr %A, i64 %off
+ store i8 42, ptr %idx, align 1
+ %i.next = add nsw i64 %i, 1
+ %cmp = icmp slt i64 %i.next, 100
+ br i1 %cmp, label %loop, label %exit
+
+exit:
+ ret void
+}
More information about the llvm-commits
mailing list