[llvm] [DA] Rewrite BanerjeeMIV test with safe APInt interval arithmetic (PR #207662)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 6 00:01:20 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: Ruoyu Qiu (cabbaken)

<details>
<summary>Changes</summary>

The old banerjeeMIVtest computed inequality bounds using SCEV arithmetic on 64-bit integers. Intermediate operations like $(A^{-} - B^{+}) \times Iterations$ could overflow i64 even when all individual coefficients and loop bounds fit, producing unsound results.

Replace the symbolic bound machinery with a self-contained APInt interval arithmetic implementation. Key design decisions:

- BanerjeeInterval holds [Lower, Upper] signed-inclusive bounds. Operations use APInt arithmetic at WideBits, chosen to guarantee no intermediate overflow: $$ WideBits = max(8, 2 \times BaseBits + MaxLevels + 8) $$ This is provably sufficient, each term product needs at most `2 \times BaseBits + 1` bits, and summing across MaxLevels terms needs at most ceil($\log_2 (MaxLevels)$) extra bits.

- Only constant affine expressions are handled. `CollectConstantAffine` requires nsw on every SCEVAddRecExpr and a SCEVConstant for both the step recurrence and the backedge-taken count. Symbolic cases bail out conservatively.

Fixes the FIXME in gcdmiv_delta_ovfl2.ll: the old code could not detect the dependence because intermediate SCEV subtraction of coefficients near INT64_MIN and INT64_MAX overflowed i64. The new code computes correct bounds at WideBits >= 138.

Adds a test in banerjee-overflow.ll for single-iteration loops and updates PR51512.ll for the more precise direction refinement.

---

Patch is 43.29 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/207662.diff


5 Files Affected:

- (modified) llvm/include/llvm/Analysis/DependenceAnalysis.h (-73) 
- (modified) llvm/lib/Analysis/DependenceAnalysis.cpp (+379-464) 
- (modified) llvm/test/Analysis/DependenceAnalysis/PR51512.ll (+1-1) 
- (modified) llvm/test/Analysis/DependenceAnalysis/banerjee-overflow.ll (+55) 
- (modified) llvm/test/Analysis/DependenceAnalysis/gcd-miv-overflow.ll (+2-4) 


``````````diff
diff --git a/llvm/include/llvm/Analysis/DependenceAnalysis.h b/llvm/include/llvm/Analysis/DependenceAnalysis.h
index 490fd4520746f..54979f8938751 100644
--- a/llvm/include/llvm/Analysis/DependenceAnalysis.h
+++ b/llvm/include/llvm/Analysis/DependenceAnalysis.h
@@ -347,21 +347,6 @@ class DependenceInfo {
     SmallBitVector Group;
   };
 
-  struct CoefficientInfo {
-    const SCEV *Coeff;
-    const SCEV *PosPart;
-    const SCEV *NegPart;
-    const SCEV *Iterations;
-  };
-
-  struct BoundInfo {
-    const SCEV *Iterations;
-    const SCEV *Upper[8];
-    const SCEV *Lower[8];
-    unsigned char Direction;
-    unsigned char DirSet;
-  };
-
   /// Returns true if two loops have the Same iteration Space and Depth. To be
   /// more specific, two loops have SameSD if they are in the same nesting
   /// depth and have the same backedge count. SameSD stands for Same iteration
@@ -609,13 +594,6 @@ class DependenceInfo {
                        const SmallBitVector &Loops,
                        FullDependence &Result) const;
 
-  /// collectCoeffInfo - Walks through the subscript, collecting each
-  /// coefficient, the associated loop bounds, and recording its positive and
-  /// negative parts for later use.
-  void collectCoeffInfo(const SCEV *Subscript, bool SrcFlag,
-                        const SCEV *&Constant,
-                        SmallVectorImpl<CoefficientInfo> &CI) const;
-
   /// Given \p Expr of the form
   ///
   ///   c_0*X_0*i_0 + c_1*X_1*i_1 + ...c_n*X_n*i_n + C
@@ -635,57 +613,6 @@ class DependenceInfo {
                                         const SCEV *&CurLoopCoeff,
                                         APInt &RunningGCD) const;
 
-  /// getPositivePart - X^+ = max(X, 0).
-  const SCEV *getPositivePart(const SCEV *X) const;
-
-  /// getNegativePart - X^- = min(X, 0).
-  const SCEV *getNegativePart(const SCEV *X) const;
-
-  /// getLowerBound - Looks through all the bounds info and
-  /// computes the lower bound given the current direction settings
-  /// at each level.
-  const SCEV *getLowerBound(ArrayRef<BoundInfo> Bound) const;
-
-  /// getUpperBound - Looks through all the bounds info and
-  /// computes the upper bound given the current direction settings
-  /// at each level.
-  const SCEV *getUpperBound(ArrayRef<BoundInfo> Bound) const;
-
-  /// exploreDirections - Hierarchically expands the direction vector
-  /// search space, combining the directions of discovered dependences
-  /// in the DirSet field of Bound. Returns the number of distinct
-  /// dependences discovered. If the dependence is disproved,
-  /// it will return 0.
-  unsigned exploreDirections(unsigned Level, ArrayRef<CoefficientInfo> A,
-                             ArrayRef<CoefficientInfo> B,
-                             MutableArrayRef<BoundInfo> Bound,
-                             const SmallBitVector &Loops,
-                             unsigned &DepthExpanded, const SCEV *Delta) const;
-
-  /// testBounds - Returns true iff the current bounds are plausible.
-  bool testBounds(unsigned char DirKind, unsigned Level,
-                  MutableArrayRef<BoundInfo> Bound, const SCEV *Delta) const;
-
-  /// findBoundsALL - Computes the upper and lower bounds for level K
-  /// using the * direction. Records them in Bound.
-  void findBoundsALL(ArrayRef<CoefficientInfo> A, ArrayRef<CoefficientInfo> B,
-                     MutableArrayRef<BoundInfo> Bound, unsigned K) const;
-
-  /// findBoundsLT - Computes the upper and lower bounds for level K
-  /// using the < direction. Records them in Bound.
-  void findBoundsLT(ArrayRef<CoefficientInfo> A, ArrayRef<CoefficientInfo> B,
-                    MutableArrayRef<BoundInfo> Bound, unsigned K) const;
-
-  /// findBoundsGT - Computes the upper and lower bounds for level K
-  /// using the > direction. Records them in Bound.
-  void findBoundsGT(ArrayRef<CoefficientInfo> A, ArrayRef<CoefficientInfo> B,
-                    MutableArrayRef<BoundInfo> Bound, unsigned K) const;
-
-  /// findBoundsEQ - Computes the upper and lower bounds for level K
-  /// using the = direction. Records them in Bound.
-  void findBoundsEQ(ArrayRef<CoefficientInfo> A, ArrayRef<CoefficientInfo> B,
-                    MutableArrayRef<BoundInfo> Bound, unsigned K) const;
-
   /// Given a linear access function, tries to recover subscripts
   /// for each dimension of the array element access.
   bool tryDelinearize(Instruction *Src, Instruction *Dst,
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index 9d5a555fb8998..702887976220a 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1922,36 +1922,167 @@ bool DependenceInfo::gcdMIVtest(const SCEV *Src, const SCEV *Dst,
 }
 
 //===----------------------------------------------------------------------===//
+
+namespace {
+struct BanerjeeInterval {
+  std::optional<APInt> Lower;
+  std::optional<APInt> Upper;
+
+  BanerjeeInterval(std::optional<APInt> Lower, std::optional<APInt> Upper)
+      : Lower(std::move(Lower)), Upper(std::move(Upper)) {}
+};
+} // namespace
+
+static APInt signedMin(const APInt &A, const APInt &B) {
+  return A.slt(B) ? A : B;
+}
+
+static APInt signedMax(const APInt &A, const APInt &B) {
+  return A.sgt(B) ? A : B;
+}
+
+static BanerjeeInterval addIntervals(const BanerjeeInterval &A,
+                                     const BanerjeeInterval &B) {
+  std::optional<APInt> Lower;
+  std::optional<APInt> Upper;
+  if (A.Lower && B.Lower)
+    Lower = *A.Lower + *B.Lower;
+  if (A.Upper && B.Upper)
+    Upper = *A.Upper + *B.Upper;
+  return BanerjeeInterval(std::move(Lower), std::move(Upper));
+}
+
+static BanerjeeInterval constantInterval(const APInt &C) {
+  return BanerjeeInterval(C, C);
+}
+
+static BanerjeeInterval emptyInterval(unsigned Bits) {
+  return BanerjeeInterval(APInt(Bits, 1, true), APInt(Bits, 0, true));
+}
+
+static bool isEmptyInterval(const BanerjeeInterval &Interval) {
+  return Interval.Lower && Interval.Upper &&
+         Interval.Lower->sgt(*Interval.Upper);
+}
+
+static BanerjeeInterval signedRangeInterval(const APInt &Coeff,
+                                            const APInt &Lower,
+                                            const APInt &Upper) {
+  APInt LowerValue = Coeff * Lower;
+  APInt UpperValue = Coeff * Upper;
+  return BanerjeeInterval(signedMin(LowerValue, UpperValue),
+                          signedMax(LowerValue, UpperValue));
+}
+
+static BanerjeeInterval variableInterval(const APInt &Coeff,
+                                         const std::optional<APInt> &Upper) {
+  APInt Zero(Coeff.getBitWidth(), 0, true);
+  if (Coeff.isZero())
+    return constantInterval(Zero);
+  if (!Upper) {
+    if (Coeff.isNegative())
+      return BanerjeeInterval(std::nullopt, Zero);
+    return BanerjeeInterval(Zero, std::nullopt);
+  }
+  return signedRangeInterval(Coeff, Zero, *Upper);
+}
+
+static BanerjeeInterval
+unboundedStrictDirectionInterval(const APInt &ACoeff, const APInt &BCoeff,
+                                 unsigned char Direction) {
+  APInt DeltaCoeff = ACoeff - BCoeff;
+
+  switch (Direction) {
+  case Dependence::DVEntry::LT: {
+    APInt Boundary = -BCoeff;
+    std::optional<APInt> Lower;
+    std::optional<APInt> Upper;
+    if (DeltaCoeff.isNonNegative() && BCoeff.isNonPositive())
+      Lower = Boundary;
+    if (DeltaCoeff.isNonPositive() && BCoeff.isNonNegative())
+      Upper = Boundary;
+    return BanerjeeInterval(std::move(Lower), std::move(Upper));
+  }
+  case Dependence::DVEntry::GT: {
+    std::optional<APInt> Lower;
+    std::optional<APInt> Upper;
+    if (ACoeff.isNonNegative() && DeltaCoeff.isNonNegative())
+      Lower = ACoeff;
+    if (ACoeff.isNonPositive() && DeltaCoeff.isNonPositive())
+      Upper = ACoeff;
+    return BanerjeeInterval(std::move(Lower), std::move(Upper));
+  }
+  default:
+    llvm_unreachable("unexpected direction");
+  }
+}
+
+static BanerjeeInterval intervalFromValues(ArrayRef<APInt> Values) {
+  assert(!Values.empty() && "expected at least one value");
+  APInt Lower = Values.front();
+  APInt Upper = Values.front();
+  for (const APInt &Value : Values.drop_front()) {
+    Lower = signedMin(Lower, Value);
+    Upper = signedMax(Upper, Value);
+  }
+  return BanerjeeInterval(std::move(Lower), std::move(Upper));
+}
+
+static APInt evaluateBanerjeeTerm(const APInt &A, const APInt &SrcIndex,
+                                  const APInt &B, const APInt &DstIndex) {
+  return A * SrcIndex - B * DstIndex;
+}
+
+static APInt extendOrTruncateKnownNonNegative(const APInt &Value,
+                                              unsigned Width) {
+  if (Value.getBitWidth() < Width)
+    return Value.zext(Width);
+  return Value.trunc(Width);
+}
+
+static APInt extendOrTruncateKnownSigned(const APInt &Value, unsigned Width) {
+  if (Value.getBitWidth() < Width)
+    return Value.sext(Width);
+  return Value.trunc(Width);
+}
+
+static std::optional<APInt> getConstantMaxIterationIndex(const Loop *L,
+                                                         unsigned BaseBits,
+                                                         unsigned WideBits,
+                                                         ScalarEvolution &SE) {
+  if (!SE.hasLoopInvariantBackedgeTakenCount(L))
+    return std::nullopt;
+
+  const SCEV *BackedgeTakenCount = SE.getBackedgeTakenCount(L);
+  if (isa<SCEVCouldNotCompute>(BackedgeTakenCount))
+    return std::nullopt;
+
+  auto *Constant = dyn_cast<SCEVConstant>(BackedgeTakenCount);
+  if (!Constant)
+    return std::nullopt;
+
+  APInt MaxIndex = Constant->getAPInt();
+  if (MaxIndex.isNegative() || MaxIndex.getActiveBits() > BaseBits)
+    return std::nullopt;
+  return extendOrTruncateKnownNonNegative(MaxIndex, WideBits);
+}
+
 // banerjeeMIVtest -
 // Use Banerjee's Inequalities to test an MIV subscript pair.
-// (Wolfe, in the race-car book, calls this the Extreme Value Test.)
-// Generally follows the discussion in Section 2.5.2 of
-//
-//    Optimizing Supercompilers for Supercomputers
-//    Michael Wolfe
+// (Wolfe calls this the Extreme Value Test; see Section 2.5.2 of
+// Optimizing Supercompilers for Supercomputers, Michael Wolfe.)
 //
-// The inequalities given on page 25 are simplified in that loops are
-// normalized so that the lower bound is always 0 and the stride is always 1.
-// For example, Wolfe gives
+// This implementation handles only constant affine expressions and constant
+// loop bounds. The original Wolfe formulae are algebraically simplified for
+// normalized loops (L_k=0, N_k=1); we instead evaluate the subscript
+// difference directly at the vertices of the constraint polytope for each
+// direction (e.g., (0,1), (0,U), (U-1,U) for <). This eliminates the
+// intermediate SCEV arithmetic whose overflow behaviour makes the legacy
+// symbolic bound formulae unsound for LLVM IR.
 //
-//     LB^<_k = (A^-_k - B_k)^- (U_k - L_k - N_k) + (A_k - B_k)L_k - B_k N_k
-//
-// where A_k is the coefficient of the kth index in the source subscript,
-// B_k is the coefficient of the kth index in the destination subscript,
-// U_k is the upper bound of the kth index, L_k is the lower bound of the Kth
-// index, and N_k is the stride of the kth index. Since all loops are normalized
-// by the SCEV package, N_k = 1 and L_k = 0, allowing us to simplify the
-// equation to
-//
-//     LB^<_k = (A^-_k - B_k)^- (U_k - 0 - 1) + (A_k - B_k)0 - B_k 1
-//            = (A^-_k - B_k)^- (U_k - 1)  - B_k
-//
-// Similar simplifications are possible for the other equations.
-//
-// When we can't determine the number of iterations for a loop,
-// we use NULL as an indicator for the worst case, infinity.
-// When computing the upper bound, NULL denotes +inf;
-// for the lower bound, NULL denotes -inf.
+// Loop bounds are backedge-taken counts (maximum normalized iteration
+// index). A single-iteration loop has bound 0, making < and > impossible.
+// Symbolic cases bail out conservatively.
 //
 // Return true if dependence disproved.
 bool DependenceInfo::banerjeeMIVtest(const SCEV *Src, const SCEV *Dst,
@@ -1962,464 +2093,248 @@ 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);
+
+  SmallVector<APInt, 4> SrcCoeffs(MaxLevels + 1, Zero);
+  SmallVector<APInt, 4> DstCoeffs(MaxLevels + 1, Zero);
+  SmallVector<std::optional<APInt>, 4> SrcMaxIterIndices(MaxLevels + 1);
+  SmallVector<std::optional<APInt>, 4> DstMaxIterIndices(MaxLevels + 1);
+  assert(Loops.size() > MaxLevels && "loop bit vector is too small");
+  assert(Result.Levels >= CommonLevels &&
+         "direction vector is too small for common levels");
+
+  auto GetConstant = [BaseBits,
+                      WideBits](const SCEV *Expr) -> std::optional<APInt> {
+    const SCEVConstant *C = dyn_cast<SCEVConstant>(Expr);
+    if (!C)
+      return std::nullopt;
+    APInt Value = C->getAPInt();
+    if (!Value.isSignedIntN(BaseBits))
+      return std::nullopt;
+    return extendOrTruncateKnownSigned(Value, WideBits);
+  };
+
+  auto CollectConstantAffine =
+      [&](const SCEV *Subscript, bool SrcFlag, MutableArrayRef<APInt> Coeffs,
+          MutableArrayRef<std::optional<APInt>> MaxIterIndices)
+      -> const SCEV * {
+    SmallBitVector SeenLevels(MaxLevels + 1);
+    while (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Subscript)) {
+      if (!AddRec->hasNoSignedWrap())
+        return nullptr;
+
+      unsigned K = SrcFlag ? mapSrcLoop(AddRec->getLoop())
+                           : mapDstLoop(AddRec->getLoop());
+      if (K == 0 || K > MaxLevels)
+        return nullptr;
+      if (SeenLevels[K])
+        return nullptr;
+      SeenLevels.set(K);
+
+      std::optional<APInt> Step = GetConstant(AddRec->getStepRecurrence(*SE));
+      if (!Step)
+        return nullptr;
+      Coeffs[K] = *Step;
+
+      if (std::optional<APInt> MaxIndex = getConstantMaxIterationIndex(
+              AddRec->getLoop(), BaseBits, WideBits, *SE))
+        MaxIterIndices[K] = *MaxIndex;
+
+      Subscript = AddRec->getStart();
     }
+
+    return Subscript;
+  };
+
+  const SCEV *A0 =
+      CollectConstantAffine(Src, true, SrcCoeffs, SrcMaxIterIndices);
+  if (!A0)
+    return false;
+  const SCEV *B0 =
+      CollectConstantAffine(Dst, false, DstCoeffs, DstMaxIterIndices);
+  if (!B0)
+    return false;
+
+  std::optional<APInt> DeltaValue;
+  if (A0 == B0) {
+    DeltaValue = Zero;
   } else {
-    ++BanerjeeIndependence;
-    Disproved = true;
-  }
-  return Disproved;
-}
-
-// Hierarchically expands the direction vector
-// search space, combining the directions of discovered dependences
-// in the DirSet field of Bound. Returns the number of distinct
-// dependences discovered. If the dependence is disproved,
-// it will return 0.
-unsigned DependenceInfo::exploreDirections(
-    unsigned Level, ArrayRef<CoefficientInfo> A, ArrayRef<CoefficientInfo> B,
-    MutableArrayRef<BoundInfo> Bound, const SmallBitVector &Loops,
-    unsigned &DepthExpanded, const SCEV *Delta) const {
-  // This algorithm has worst case complexity of O(3^n), where 'n' is the number
-  // of common loop levels. To avoid excessive compile-time, pessimize all the
-  // results and immediately return when the number of common levels is beyond
-  // the given threshold.
-  if (CommonLevels > MIVMaxLevelThreshold) {
-    LLVM_DEBUG(dbgs() << "Number of common levels exceeded the threshold. MIV "
-                         "direction exploration is terminated.\n");
-    for (unsigned K = 1; K <= CommonLevels; ++K)
-      if (Loops[K])
-        Bound[K].DirSet = Dependence::DVEntry::ALL;
-    return 1;
-  }
-
-  if (Level > CommonLevels) {
-    // record result
-    LLVM_DEBUG(dbgs() << "\t[");
-    for (unsigned K = 1; K <= CommonLevels; ++K) {
-      if (Loops[K]) {
-        Bound[K].DirSet |= Bound[K].Direction;
-#ifndef NDEBUG
-        switch (Bound[K].Direction) {
-        case Dependence::DVEntry::LT:
-          LLVM_DEBUG(dbgs() << " <");
-          break;
-        case Dependence::DVEntry::EQ:
-          LLVM_DEBUG(dbgs() << " =");
-          break;
-        case Dependence::DVEntry::GT:
-          LLVM_DEBUG(dbgs() << " >");
-          break;
-        case Dependence::DVEntry::ALL:
-          LLVM_DEBUG(dbgs() << " *");
-          break;
-        default:
-          llvm_unreachable("unexpected Bound[K].Direction");
-        }
-#endif
-      }
-    }
-    LLVM_DEBUG(dbgs() << " ]\n");
-    return 1;
-  }
-  if (Loops[Level]) {
-    if (Level > DepthExpanded) {
-      DepthExpanded = Level;
-      // compute bounds for <, =, > at current level
-      findBoundsLT(A, B, Bound, Level);
-      findBoundsGT(A, B, Bound, Level);
-      findBoundsEQ(A, B, Bound, Level);
-#ifndef NDEBUG
-      LLVM_DEBUG(dbgs() << "\tBound for level = " << Level << '\n');
-      LLVM_DEBUG(dbgs() << "\t    <\t");
-      if (Bound[Level].Lower[Dependence::DVEntry::LT])
-        LLVM_DEBUG(dbgs() << *Bound[Level].Lower[Dependence::DVEntry::LT]
-                          << '\t');
-      else
-        LLVM_DEBUG(dbgs() << "-inf\t");
-      if (Bound[Level].Upper[Dependence::DVEntry::LT])
-        LLVM_DEBUG(dbgs() << *Bound[Level].Upper[Dependence::DVEntry::LT]
-                          << '\n');
-      else
-        LLVM_DEBUG(dbgs() << "+inf\n");
-      LLVM_DEBUG(dbgs() << "\t    =\t");
-      if (Bound[Level].Lower[Dependence::DVEntry::EQ])
-        LLVM_DEBUG(dbgs() << *Bound[Level].Lower[Dependence::DVEntry::EQ]
-                          << '\t');
-      else
-        LLVM_DEBUG(dbgs() << "-inf\t");
-      if (Bound[Level].Upper[Dependence::DVEntry::EQ])
-        LLVM_DEBUG(dbgs() << *Bound[Level].Upper[Depende...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/207662


More information about the llvm-commits mailing list