[llvm] [DA] Rewrite BanerjeeMIV test with safe APInt interval arithmetic (PR #207662)
Ruoyu Qiu via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 15 04:30:57 PDT 2026
================
@@ -1962,464 +2093,251 @@ bool DependenceInfo::banerjeeMIVtest(const SCEV *Src, const SCEV *Dst,
LLVM_DEBUG(dbgs() << "starting Banerjee\n");
++BanerjeeApplications;
- LLVM_DEBUG(dbgs() << " Src = " << *Src << '\n');
- const SCEV *A0;
- SmallVector<CoefficientInfo, 4> A;
- collectCoeffInfo(Src, true, A0, A);
- LLVM_DEBUG(dbgs() << " Dst = " << *Dst << '\n');
- const SCEV *B0;
- SmallVector<CoefficientInfo, 4> B;
- collectCoeffInfo(Dst, false, B0, B);
- SmallVector<BoundInfo, 4> Bound(MaxLevels + 1);
- const SCEV *Delta = minusSCEVNoSignedOverflow(B0, A0, *SE);
- if (!Delta)
- return false;
- LLVM_DEBUG(dbgs() << "\tDelta = " << *Delta << '\n');
-
- // Compute bounds for all the * directions.
- LLVM_DEBUG(dbgs() << "\tBounds[*]\n");
- for (unsigned K = 1; K <= MaxLevels; ++K) {
- Bound[K].Iterations = A[K].Iterations ? A[K].Iterations : B[K].Iterations;
- Bound[K].Direction = Dependence::DVEntry::ALL;
- Bound[K].DirSet = Dependence::DVEntry::NONE;
- findBoundsALL(A, B, Bound, K);
-#ifndef NDEBUG
- LLVM_DEBUG(dbgs() << "\t " << K << '\t');
- if (Bound[K].Lower[Dependence::DVEntry::ALL])
- LLVM_DEBUG(dbgs() << *Bound[K].Lower[Dependence::DVEntry::ALL] << '\t');
- else
- LLVM_DEBUG(dbgs() << "-inf\t");
- if (Bound[K].Upper[Dependence::DVEntry::ALL])
- LLVM_DEBUG(dbgs() << *Bound[K].Upper[Dependence::DVEntry::ALL] << '\n');
- else
- LLVM_DEBUG(dbgs() << "+inf\n");
-#endif
- }
- // Test the *, *, *, ... case.
- bool Disproved = false;
- if (testBounds(Dependence::DVEntry::ALL, 0, Bound, Delta)) {
- // Explore the direction vector hierarchy.
- unsigned DepthExpanded = 0;
- unsigned NewDeps =
- exploreDirections(1, A, B, Bound, Loops, DepthExpanded, Delta);
- if (NewDeps > 0) {
- bool Improved = false;
- for (unsigned K = 1; K <= CommonLevels; ++K) {
- if (Loops[K]) {
- unsigned Old = Result.DV[K - 1].Direction;
- Result.DV[K - 1].Direction = Old & Bound[K].DirSet;
- Improved |= Old != Result.DV[K - 1].Direction;
- if (!Result.DV[K - 1].Direction) {
- Improved = false;
- Disproved = true;
- break;
- }
- }
- }
- if (Improved)
- ++BanerjeeSuccesses;
- } else {
- ++BanerjeeIndependence;
- Disproved = true;
+ unsigned SrcBits = SE->getTypeSizeInBits(Src->getType());
+ unsigned DstBits = SE->getTypeSizeInBits(Dst->getType());
+ unsigned BaseBits = std::max(SrcBits, DstBits);
+ // Accepted coefficients and constants fit in signed BaseBits, and loop
+ // bounds fit in unsigned BaseBits. WideBits is large enough for products of
+ // those values and for summing one interval term per loop level.
+ unsigned WideBits = std::max(8u, 2 * BaseBits + MaxLevels + 8);
+ APInt Zero(WideBits, 0, true);
----------------
cabbaken wrote:
I tried to understand this; I'm not sure if I'm on the right track. Here are my thoughts:
- Effective domain: index combinations where the expression actually executes.
- Entire rectangular domain: every combination from 0 to each loop’s BTC
For the memory access inside the inner loop, the Effective domain has 0 ≤ i < 1000 and 0 ≤ j < INT64_MAX - 1000. The SCEV for i + j can have nsw because
it does not overflow for any iteration where the expression actually executes.
Banerjee analysis does not know the i < 1000 guard, so it considers the larger Entire rectangular domain using the complete loop bounds. This contains
hypothetical (i, j) combinations where i + j would exceed the original signed 64-bit range.
The new implementation evaluates those combinations using WideBits, so the analysis arithmetic itself does not overflow. Those hypothetical combinations
only enlarge the interval, making the result less precise but still conservative.
https://github.com/llvm/llvm-project/pull/207662
More information about the llvm-commits
mailing list