-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[DA] Fix symbolic RDIV and Strong SIV with impossible assumptions (PR149501) #157761
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/sebpop/pr149977
Are you sure you want to change the base?
Conversation
…149501) Address GitHub issue llvm#149501. Fixes incorrect independence conclusions in symbolic RDIV test and improves Strong SIV bound checking for symbolic expressions. The patch fixes: - Strong SIV: Improve bound checking for symbolic expressions, avoid impossible assumptions like '0 <= -1' when Delta and UpperBound have inverse relationships. - Symbolic RDIV: Detect when C2-C1 == N1+1 creates trivially true comparisons leading to wrong 'none!' conclusions, now returns conservative analysis. The symbolic RDIV fix prevents cases where expressions like (m-n) > (m-n-1) incorrectly conclude independence. Now returns conservative 'output [*|<]!' instead of wrong 'none!' for symbolic expressions with problematic bounds.
@llvm/pr-subscribers-llvm-analysis Author: Sebastian Pop (sebpop) ChangesAddress GitHub issue #149501. The patch fixes:
Patch is 29.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/157761.diff 10 Files Affected:
diff --git a/llvm/include/llvm/Analysis/DependenceAnalysis.h b/llvm/include/llvm/Analysis/DependenceAnalysis.h
index f66c79d915665..300cfb73af5c1 100644
--- a/llvm/include/llvm/Analysis/DependenceAnalysis.h
+++ b/llvm/include/llvm/Analysis/DependenceAnalysis.h
@@ -285,7 +285,8 @@ class LLVM_ABI FullDependence final : public Dependence {
class DependenceInfo {
public:
DependenceInfo(Function *F, AAResults *AA, ScalarEvolution *SE, LoopInfo *LI)
- : AA(AA), SE(SE), LI(LI), F(F) {}
+ : AA(AA), SE(SE), LI(LI), F(F), Assumptions({}, *SE),
+ UnderRuntimeAssumptions(false) {}
/// Handle transitive invalidation when the cached analysis results go away.
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA,
@@ -355,7 +356,33 @@ class DependenceInfo {
ScalarEvolution *SE;
LoopInfo *LI;
Function *F;
- SmallVector<const SCEVPredicate *, 4> Assumptions;
+
+ /// Runtime assumptions collected during dependence analysis.
+ ///
+ /// The dependence analysis employs a cascade of tests from simple to complex:
+ /// ZIV -> SIV (Strong/Weak-Crossing/Weak-Zero) -> RDIV -> MIV -> Banerjee.
+ /// Each test attempts to characterize the dependence with increasing
+ /// precision.
+ ///
+ /// Assumption Management Strategy:
+ /// - Each test may require runtime assumptions (e.g., "coefficient != 0")
+ /// to provide precise analysis.
+ /// - If UnderRuntimeAssumptions=true: tests can add assumptions and continue.
+ /// - If UnderRuntimeAssumptions=false: tests that need assumptions fail
+ /// gracefully, allowing more complex tests to attempt analysis.
+ /// - Only assumptions from successful tests contribute to the final result.
+ /// - SCEVUnionPredicate automatically deduplicates redundant assumptions.
+ ///
+ /// This design ensures:
+ /// 1. Simpler tests get priority (better performance).
+ /// 2. Complex tests serve as fallbacks when simple tests fail.
+ /// 3. No unnecessary runtime checks from failed test attempts.
+ /// 4. Maintains the intended cascade behavior of the dependence analysis.
+ SCEVUnionPredicate Assumptions;
+
+ /// Indicates whether runtime assumptions are collected during the analysis.
+ /// When false, dependence tests that would require runtime assumptions fail.
+ bool UnderRuntimeAssumptions;
/// Subscript - This private struct represents a pair of subscripts from
/// a pair of potentially multi-dimensional array references. We use a
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index da86a8d2cc9c0..ef7ba48c8fa9a 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1243,16 +1243,76 @@ bool DependenceInfo::strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
if (const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->getType())) {
LLVM_DEBUG(dbgs() << "\t UpperBound = " << *UpperBound);
LLVM_DEBUG(dbgs() << ", " << *UpperBound->getType() << "\n");
+
+ // Handle negative upper bound - loop doesn't execute.
+ if (SE->isKnownNegative(UpperBound)) {
+ LLVM_DEBUG(dbgs() << "\t Negative upper bound - no dependence\n");
+ ++StrongSIVindependence;
+ ++StrongSIVsuccesses;
+ return true;
+ }
+
const SCEV *AbsDelta =
SE->isKnownNonNegative(Delta) ? Delta : SE->getNegativeSCEV(Delta);
const SCEV *AbsCoeff =
SE->isKnownNonNegative(Coeff) ? Coeff : SE->getNegativeSCEV(Coeff);
const SCEV *Product = SE->getMulExpr(UpperBound, AbsCoeff);
+
if (isKnownPredicate(CmpInst::ICMP_SGT, AbsDelta, Product)) {
- // Distance greater than trip count - no dependence
- ++StrongSIVindependence;
- ++StrongSIVsuccesses;
- return true;
+ // Check if this involves symbolic expressions where we might be too
+ // conservative.
+ if (isa<SCEVUnknown>(Delta) || isa<SCEVUnknown>(Coeff) ||
+ !isa<SCEVConstant>(AbsDelta) || !isa<SCEVConstant>(Product)) {
+ // Check if the assumption would be meaningful and not trivially
+ // impossible. For relationships like Delta=n-m, UpperBound=m-n-1, the
+ // assumption |n-m| <= (m-n-1) can be impossible (e.g., 0 <= -1 when
+ // n=m).
+ bool MeaningfulAssumption = true;
+
+ // Detect cases where Delta and UpperBound have inverse relationships
+ // that could lead to impossible assumptions.
+ if (isa<SCEVAddExpr>(Delta) && isa<SCEVAddExpr>(UpperBound)) {
+ // Look for patterns where UpperBound = -Delta - 1 (or similar).
+ const SCEV *NegDelta = SE->getNegativeSCEV(Delta);
+ const SCEV *NegDeltaMinusOne =
+ SE->getAddExpr(NegDelta, SE->getConstant(Delta->getType(), -1));
+ if (UpperBound == NegDeltaMinusOne) {
+ MeaningfulAssumption = false;
+ LLVM_DEBUG(dbgs() << "\t Detected inverse relationship - "
+ "assumption would be impossible\n");
+ }
+ }
+
+ if (MeaningfulAssumption && !SE->isKnownNonPositive(Product)) {
+ // For symbolic expressions, add runtime assumption rather than
+ // rejecting.
+ const SCEVPredicate *BoundPred =
+ SE->getComparePredicate(ICmpInst::ICMP_SLE, AbsDelta, Product);
+ if (UnderRuntimeAssumptions) {
+ SmallVector<const SCEVPredicate *, 4> NewPreds(
+ Assumptions.getPredicates());
+ NewPreds.push_back(BoundPred);
+ const_cast<DependenceInfo *>(this)->Assumptions =
+ SCEVUnionPredicate(NewPreds, *SE);
+ LLVM_DEBUG(dbgs() << "\t Added runtime bound assumption\n");
+ } else {
+ // Cannot add runtime assumptions, let more complex tests try.
+ LLVM_DEBUG(dbgs() << "\t Would need runtime bound assumption "
+ "but not allowed. Failing this test.\n");
+ return false;
+ }
+ } else {
+ LLVM_DEBUG(dbgs() << "\t Cannot add meaningful assumption\n");
+ // When bound check fails and we can't add meaningful assumptions,
+ // this test cannot handle this case reliably.
+ return false;
+ }
+ } else {
+ // Distance definitely greater than trip count - no dependence.
+ ++StrongSIVindependence;
+ ++StrongSIVsuccesses;
+ return true;
+ }
}
}
@@ -1293,9 +1353,40 @@ bool DependenceInfo::strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
Result.DV[Level].Distance = Delta; // since X/1 == X
NewConstraint.setDistance(Delta, CurLoop);
} else {
- Result.Consistent = false;
- NewConstraint.setLine(Coeff, SE->getNegativeSCEV(Coeff),
- SE->getNegativeSCEV(Delta), CurLoop);
+ // Try symbolic division: Distance = Delta / Coeff.
+ if (const SCEV *Distance = SE->getUDivExactExpr(Delta, Coeff)) {
+ LLVM_DEBUG(dbgs() << "\t Symbolic distance = " << *Distance << "\n");
+ Result.DV[Level].Distance = Distance;
+ NewConstraint.setDistance(Distance, CurLoop);
+ } else {
+ // Cannot compute exact division - check if we can add runtime
+ // assumptions.
+ if (isa<SCEVUnknown>(Coeff) && !SE->isKnownNonZero(Coeff)) {
+ // Add runtime assumption that coefficient is non-zero for division.
+ const SCEV *Zero = SE->getZero(Coeff->getType());
+ const SCEVPredicate *NonZeroPred =
+ SE->getComparePredicate(ICmpInst::ICMP_NE, Coeff, Zero);
+ if (UnderRuntimeAssumptions) {
+ SmallVector<const SCEVPredicate *, 4> NewPreds(
+ Assumptions.getPredicates());
+ NewPreds.push_back(NonZeroPred);
+ const_cast<DependenceInfo *>(this)->Assumptions =
+ SCEVUnionPredicate(NewPreds, *SE);
+ LLVM_DEBUG(dbgs() << "\t Added runtime assumption: " << *Coeff
+ << " != 0 for symbolic division\n");
+ } else {
+ // Cannot add runtime assumptions, this test fails.
+ LLVM_DEBUG(dbgs()
+ << "\t Would need runtime assumption " << *Coeff
+ << " != 0 but not allowed. Failing this test.\n");
+ return false;
+ }
+ }
+
+ Result.Consistent = false;
+ NewConstraint.setLine(Coeff, SE->getNegativeSCEV(Coeff),
+ SE->getNegativeSCEV(Delta), CurLoop);
+ }
}
// maybe we can get a useful direction
@@ -2135,8 +2226,39 @@ bool DependenceInfo::symbolicRDIVtest(const SCEV *A1, const SCEV *A2,
const SCEV *N2 = collectUpperBound(Loop2, A1->getType());
LLVM_DEBUG(if (N1) dbgs() << "\t N1 = " << *N1 << "\n");
LLVM_DEBUG(if (N2) dbgs() << "\t N2 = " << *N2 << "\n");
+
const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
+
+ // Check for negative or problematic upper bounds
+ auto CheckUpperBound = [&](const SCEV *N, const SCEV *Delta,
+ const char *Name) -> bool {
+ if (!N)
+ // No bound to check.
+ return true;
+
+ if (SE->isKnownNegative(N)) {
+ LLVM_DEBUG(dbgs() << "\t " << Name
+ << " is negative - analysis unreliable\n");
+ return false;
+ }
+
+ // Check for degenerate cases where upper bounds are too close to the delta
+ // values. This can happen when N is an expression like (Delta - 1), leading
+ // to trivially true comparisons like Delta > (Delta - 1).
+ const SCEV *NPlusOne = SE->getAddExpr(N, SE->getOne(N->getType()));
+ if (Delta == NPlusOne) {
+ LLVM_DEBUG(dbgs() << "\t Degenerate case: Delta == " << Name
+ << "+1 - analysis unreliable\n");
+ return false;
+ }
+ // Bound is OK.
+ return true;
+ };
+
+ if (!CheckUpperBound(N1, C2_C1, "N1") || !CheckUpperBound(N2, C1_C2, "N2"))
+ return false;
+
LLVM_DEBUG(dbgs() << "\t C2 - C1 = " << *C2_C1 << "\n");
LLVM_DEBUG(dbgs() << "\t C1 - C2 = " << *C1_C2 << "\n");
if (SE->isKnownNonNegative(A1)) {
@@ -3567,7 +3689,7 @@ bool DependenceInfo::invalidate(Function &F, const PreservedAnalyses &PA,
}
SCEVUnionPredicate DependenceInfo::getRuntimeAssumptions() const {
- return SCEVUnionPredicate(Assumptions, *SE);
+ return Assumptions;
}
// depends -
@@ -3584,7 +3706,12 @@ SCEVUnionPredicate DependenceInfo::getRuntimeAssumptions() const {
std::unique_ptr<Dependence>
DependenceInfo::depends(Instruction *Src, Instruction *Dst,
bool UnderRuntimeAssumptions) {
- SmallVector<const SCEVPredicate *, 4> Assume;
+ // Set the flag for whether we're allowed to add runtime assumptions.
+ this->UnderRuntimeAssumptions = UnderRuntimeAssumptions;
+
+ // Clear any previous assumptions
+ Assumptions = SCEVUnionPredicate({}, *SE);
+
bool PossiblyLoopIndependent = true;
if (Src == Dst)
PossiblyLoopIndependent = false;
@@ -3596,8 +3723,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
if (!isLoadOrStore(Src) || !isLoadOrStore(Dst)) {
// can only analyze simple loads and stores, i.e., no calls, invokes, etc.
LLVM_DEBUG(dbgs() << "can only handle simple loads and stores\n");
- return std::make_unique<Dependence>(Src, Dst,
- SCEVUnionPredicate(Assume, *SE));
+ return std::make_unique<Dependence>(Src, Dst, getRuntimeAssumptions());
}
const MemoryLocation &DstLoc = MemoryLocation::get(Dst);
@@ -3608,8 +3734,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
case AliasResult::PartialAlias:
// cannot analyse objects if we don't understand their aliasing.
LLVM_DEBUG(dbgs() << "can't analyze may or partial alias\n");
- return std::make_unique<Dependence>(Src, Dst,
- SCEVUnionPredicate(Assume, *SE));
+ return std::make_unique<Dependence>(Src, Dst, getRuntimeAssumptions());
case AliasResult::NoAlias:
// If the objects noalias, they are distinct, accesses are independent.
LLVM_DEBUG(dbgs() << "no alias\n");
@@ -3623,8 +3748,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
// The dependence test gets confused if the size of the memory accesses
// differ.
LLVM_DEBUG(dbgs() << "can't analyze must alias with different sizes\n");
- return std::make_unique<Dependence>(Src, Dst,
- SCEVUnionPredicate(Assume, *SE));
+ return std::make_unique<Dependence>(Src, Dst, getRuntimeAssumptions());
}
Value *SrcPtr = getLoadStorePointerOperand(Src);
@@ -3643,8 +3767,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
// We check this upfront so we don't crash in cases where getMinusSCEV()
// returns a SCEVCouldNotCompute.
LLVM_DEBUG(dbgs() << "can't analyze SCEV with different pointer base\n");
- return std::make_unique<Dependence>(Src, Dst,
- SCEVUnionPredicate(Assume, *SE));
+ return std::make_unique<Dependence>(Src, Dst, getRuntimeAssumptions());
}
// Even if the base pointers are the same, they may not be loop-invariant. It
@@ -3656,8 +3779,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
if (!isLoopInvariant(SrcBase, SrcLoop) ||
!isLoopInvariant(DstBase, DstLoop)) {
LLVM_DEBUG(dbgs() << "The base pointer is not loop invariant.\n");
- return std::make_unique<Dependence>(Src, Dst,
- SCEVUnionPredicate(Assume, *SE));
+ return std::make_unique<Dependence>(Src, Dst, getRuntimeAssumptions());
}
uint64_t EltSize = SrcLoc.Size.toRaw();
@@ -3665,35 +3787,40 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
// Check that memory access offsets are multiples of element sizes.
- if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
- !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
+ SmallVector<const SCEVPredicate *, 4> TempAssumptions;
+ if (!SE->isKnownMultipleOf(SrcEv, EltSize, TempAssumptions) ||
+ !SE->isKnownMultipleOf(DstEv, EltSize, TempAssumptions)) {
LLVM_DEBUG(dbgs() << "can't analyze SCEV with different offsets\n");
- return std::make_unique<Dependence>(Src, Dst,
- SCEVUnionPredicate(Assume, *SE));
+ return std::make_unique<Dependence>(Src, Dst, getRuntimeAssumptions());
}
- if (!Assume.empty()) {
- if (!UnderRuntimeAssumptions)
- return std::make_unique<Dependence>(Src, Dst,
- SCEVUnionPredicate(Assume, *SE));
- // Add non-redundant assumptions.
- unsigned N = Assumptions.size();
- for (const SCEVPredicate *P : Assume) {
- bool Implied = false;
- for (unsigned I = 0; I != N && !Implied; I++)
- if (Assumptions[I]->implies(P, *SE))
- Implied = true;
- if (!Implied)
- Assumptions.push_back(P);
+ // Add any new assumptions from the isKnownMultipleOf calls
+ if (!TempAssumptions.empty()) {
+ if (UnderRuntimeAssumptions) {
+ SmallVector<const SCEVPredicate *, 4> NewPreds(
+ Assumptions.getPredicates());
+ NewPreds.append(TempAssumptions.begin(), TempAssumptions.end());
+ const_cast<DependenceInfo *>(this)->Assumptions =
+ SCEVUnionPredicate(NewPreds, *SE);
+ } else {
+ // Runtime assumptions needed but not allowed.
+ // Return confused dependence since we cannot proceed with precise
+ // analysis.
+ LLVM_DEBUG(dbgs() << "Runtime assumptions needed for offset analysis but "
+ "not allowed\n");
+ return std::make_unique<Dependence>(Src, Dst, getRuntimeAssumptions());
}
}
+ // Assert that we haven't added runtime assumptions when not allowed
+ assert(UnderRuntimeAssumptions || Assumptions.isAlwaysTrue());
+
establishNestingLevels(Src, Dst);
LLVM_DEBUG(dbgs() << " common nesting levels = " << CommonLevels << "\n");
LLVM_DEBUG(dbgs() << " maximum nesting levels = " << MaxLevels << "\n");
- FullDependence Result(Src, Dst, SCEVUnionPredicate(Assume, *SE),
- PossiblyLoopIndependent, CommonLevels);
+ FullDependence Result(Src, Dst, Assumptions, PossiblyLoopIndependent,
+ CommonLevels);
++TotalArrayPairs;
unsigned Pairs = 1;
@@ -4036,6 +4163,10 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
return nullptr;
}
+ // Assert that we haven't added runtime assumptions when not allowed
+ assert(UnderRuntimeAssumptions || Assumptions.isAlwaysTrue());
+
+ Result.Assumptions = getRuntimeAssumptions();
return std::make_unique<FullDependence>(std::move(Result));
}
diff --git a/llvm/test/Analysis/DependenceAnalysis/BasePtrBug.ll b/llvm/test/Analysis/DependenceAnalysis/BasePtrBug.ll
index 81e461a5e092d..8933c5fa6520a 100644
--- a/llvm/test/Analysis/DependenceAnalysis/BasePtrBug.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/BasePtrBug.ll
@@ -18,7 +18,7 @@ define void @test1(ptr nocapture %A, ptr nocapture %B, i32 %N) #0 {
; CHECK-NEXT: Src: %0 = load i32, ptr %gep.0, align 4 --> Dst: %0 = load i32, ptr %gep.0, align 4
; CHECK-NEXT: da analyze - none!
; CHECK-NEXT: Src: %0 = load i32, ptr %gep.0, align 4 --> Dst: %1 = load i32, ptr %gep.1, align 4
-; CHECK-NEXT: da analyze - input [*|<]!
+; CHECK-NEXT: da analyze - consistent input [((-4 * (sext i32 %div to i64))<nsw> /u 4)|<]!
; CHECK-NEXT: Src: %0 = load i32, ptr %gep.0, align 4 --> Dst: store i32 %add, ptr %gep.B, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: %1 = load i32, ptr %gep.1, align 4 --> Dst: %1 = load i32, ptr %gep.1, align 4
diff --git a/llvm/test/Analysis/DependenceAnalysis/DADelin.ll b/llvm/test/Analysis/DependenceAnalysis/DADelin.ll
index 8f94a455d3724..6e50712d6b458 100644
--- a/llvm/test/Analysis/DependenceAnalysis/DADelin.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/DADelin.ll
@@ -648,7 +648,7 @@ define void @coeff_may_negative(ptr %a, i32 %k) {
; 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: 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: da analyze - consistent output [((-1 * %k) /u %k)|<]!
; 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!
;
@@ -687,7 +687,7 @@ define void @coeff_positive(ptr %a, i32 %k) {
; 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: 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: da analyze - consistent output [((-1 * %k) /u %k)|<]!
; 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!
;
diff --git a/llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll b/llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll
index d9ccea55dd478..719a62a3d5113 100644
--- a/llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll
@@ -34,8 +34,6 @@ define i32 @alias_with_parametric_offset(ptr nocapture %A, i64 %n) {
; CHECK-NEXT: Equal predicate: (zext i2 (trunc i64 %n to i2) to i64) == 0
; CHECK-NEXT: Src: %0 = load i32, ptr %A, align 1 --> Dst: %0 = load i32, ptr %A, align 1
; CHECK-NEXT: da analyze - none!
-; CHECK-NEXT: Runtime Assumptions:
-; CHECK-NEXT: Equal predicate: (zext i2 (trunc i64 %n to i2) to i64) == 0
;
entry:
%arrayidx = getelementptr inbounds i8, ptr %A, i64 %n
@@ -56,7 +54,6 @@ define i32 @alias_with_parametric_expr(ptr nocapture %A, i64 %n, i64 %m) {
; 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: 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 pre...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using Stacked Pull Requests.
// Handle negative upper bound - loop doesn't execute. | ||
if (SE->isKnownNegative(UpperBound)) { | ||
LLVM_DEBUG(dbgs() << "\t Negative upper bound - no dependence\n"); | ||
++StrongSIVindependence; | ||
++StrongSIVsuccesses; | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Although I haven't looked at the other parts) I think this is incorrect. In general, UpperBound
is an unsigned value, may be interpreted as negative in a signed sense. That is, isKnownNegative(UpperBound)
does not mean that the loop will not be executed.
Thanks for the pointer: a very helpful read. |
Address GitHub issue #149501.
Fixes incorrect independence conclusions in symbolic RDIV test and improves
Strong SIV bound checking for symbolic expressions.
The patch fixes:
Strong SIV: Improve bound checking for symbolic expressions, avoid impossible
assumptions like
0 <= -1
when Delta and UpperBound have inverse relationships.Symbolic RDIV: Detect when
C2-C1 == N1+1
creates trivially true comparisonsleading to wrong
none!
conclusions, now returns conservative analysis. Thesymbolic RDIV fix prevents cases where expressions like
(m-n) > (m-n-1)
incorrectly conclude independence. Now returns conservative
output [*|<]!
instead of wrong
none!
for symbolic expressions with problematic bounds.