github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/Dialect/SDBM/SDBM.cpp (about)

     1  //===- SDBM.cpp - MLIR SDBM implementation --------------------------------===//
     2  //
     3  // Copyright 2019 The MLIR Authors.
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //   http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  // =============================================================================
    17  //
    18  // A striped difference-bound matrix (SDBM) is a set in Z^N (or R^N) defined
    19  // as {(x_1, ... x_n) | f(x_1, ... x_n) >= 0} where f is an SDBM expression.
    20  //
    21  //===----------------------------------------------------------------------===//
    22  
    23  #include "mlir/Dialect/SDBM/SDBM.h"
    24  #include "mlir/Dialect/SDBM/SDBMExpr.h"
    25  
    26  #include "llvm/ADT/DenseMap.h"
    27  #include "llvm/ADT/SetVector.h"
    28  #include "llvm/Support/FormatVariadic.h"
    29  #include "llvm/Support/raw_ostream.h"
    30  
    31  using namespace mlir;
    32  
    33  // Helper function for SDBM construction that collects information necessary to
    34  // start building an SDBM in one sweep.  In particular, it records the largest
    35  // position of a dimension in `dim`, that of a symbol in `symbol` as well as
    36  // collects all unique stripe expressions in `stripes`.  Uses SetVector to
    37  // ensure these expressions always have the same order.
    38  static void collectSDBMBuildInfo(SDBMExpr expr, int &dim, int &symbol,
    39                                   llvm::SmallSetVector<SDBMExpr, 8> &stripes) {
    40    struct Visitor : public SDBMVisitor<Visitor> {
    41      void visitDim(SDBMDimExpr dimExpr) {
    42        int p = dimExpr.getPosition();
    43        if (p > maxDimPosition)
    44          maxDimPosition = p;
    45      }
    46      void visitSymbol(SDBMSymbolExpr symbExpr) {
    47        int p = symbExpr.getPosition();
    48        if (p > maxSymbPosition)
    49          maxSymbPosition = p;
    50      }
    51      void visitStripe(SDBMStripeExpr stripeExpr) { stripes.insert(stripeExpr); }
    52  
    53      Visitor(llvm::SmallSetVector<SDBMExpr, 8> &stripes) : stripes(stripes) {}
    54  
    55      int maxDimPosition = -1;
    56      int maxSymbPosition = -1;
    57      llvm::SmallSetVector<SDBMExpr, 8> &stripes;
    58    };
    59  
    60    Visitor visitor(stripes);
    61    visitor.walkPostorder(expr);
    62    dim = std::max(dim, visitor.maxDimPosition);
    63    symbol = std::max(symbol, visitor.maxSymbPosition);
    64  }
    65  
    66  namespace {
    67  // Utility class for SDBMBuilder.  Represents a value that can be inserted in
    68  // the SDB matrix that corresponds to "v0 - v1 + C <= 0", where v0 and v1 is
    69  // any combination of the positive and negative positions.  Since multiple
    70  // variables can be declared equal to the same stripe expression, the
    71  // constraints on this expression must be reflected to all these variables.  For
    72  // example, if
    73  //   d0 = s0 # 42
    74  //   d1 = s0 # 42
    75  //   d2 = s1 # 2
    76  //   d3 = s1 # 2
    77  // the constraint
    78  //   s0 # 42 - s1 # 2 <= C
    79  // should be reflected in the DB matrix as
    80  //   d0 - d2 <= C
    81  //   d1 - d2 <= C
    82  //   d0 - d3 <= C
    83  //   d1 - d3 <= C
    84  // since the DB matrix has no knowledge of the transitive equality between d0,
    85  // d1 and s0 # 42 as well as between d2, d3 and s1 # 2.  This knowledge can be
    86  // obtained by computing a transitive closure, which is impossible until the
    87  // DBM is actually built.
    88  struct SDBMBuilderResult {
    89    // Positions in the matrix of the variables taken with the "+" sign in the
    90    // difference expression, 0 if it is a constant rather than a variable.
    91    llvm::SmallVector<unsigned, 2> positivePos;
    92  
    93    // Positions in the matrix of the variables taken with the "-" sign in the
    94    // difference expression, 0 if it is a constant rather than a variable.
    95    llvm::SmallVector<unsigned, 2> negativePos;
    96  
    97    // Constant value in the difference expression.
    98    int64_t value = 0;
    99  };
   100  
   101  // Visitor for building an SDBM from SDBM expressions.  After traversing an SDBM
   102  // expression, produces an update to the SDB matrix specifying the positions in
   103  // the matrix and the negated value that should be stored.  Both the positive
   104  // and the negative positions may be lists of indices in cases where multiple
   105  // variables are equal to the same stripe expression.  In such cases, the update
   106  // applies to the cross product of positions because elements involved in the
   107  // update are (transitively) equal and should have the same constraints, but we
   108  // may not have an explicit equality for them.
   109  struct SDBMBuilder : public SDBMVisitor<SDBMBuilder, SDBMBuilderResult> {
   110  public:
   111    // A difference expression produces both the positive and the negative
   112    // coordinate in the matrix, recursively traversing the LHS and the RHS. The
   113    // value is the difference between values obtained from LHS and RHS.
   114    SDBMBuilderResult visitDiff(SDBMDiffExpr diffExpr) {
   115      auto lhs = visit(diffExpr.getLHS());
   116      auto rhs = visit(diffExpr.getRHS());
   117      assert(lhs.negativePos.size() == 1 && lhs.negativePos[0] == 0 &&
   118             "unexpected negative expression in a difference expression");
   119      assert(rhs.negativePos.size() == 1 && lhs.negativePos[0] == 0 &&
   120             "unexpected negative expression in a difference expression");
   121  
   122      SDBMBuilderResult result;
   123      result.positivePos = lhs.positivePos;
   124      result.negativePos = rhs.positivePos;
   125      result.value = lhs.value - rhs.value;
   126      return result;
   127    }
   128  
   129    // An input expression is always taken with the "+" sign and therefore
   130    // produces a positive coordinate keeping the negative coordinate zero for an
   131    // eventual constant.
   132    SDBMBuilderResult visitInput(SDBMInputExpr expr) {
   133      SDBMBuilderResult r;
   134      r.positivePos.push_back(linearPosition(expr));
   135      r.negativePos.push_back(0);
   136      return r;
   137    }
   138  
   139    // A stripe expression is always equal to one or more variables, which may be
   140    // temporaries, and appears with a "+" sign in the SDBM expression tree. Take
   141    // the positions of the corresponding variables as positive coordinates.
   142    SDBMBuilderResult visitStripe(SDBMStripeExpr expr) {
   143      SDBMBuilderResult r;
   144      assert(pointExprToStripe.count(expr));
   145      r.positivePos = pointExprToStripe[expr];
   146      r.negativePos.push_back(0);
   147      return r;
   148    }
   149  
   150    // A constant expression has both coordinates at zero.
   151    SDBMBuilderResult visitConstant(SDBMConstantExpr expr) {
   152      SDBMBuilderResult r;
   153      r.positivePos.push_back(0);
   154      r.negativePos.push_back(0);
   155      r.value = expr.getValue();
   156      return r;
   157    }
   158  
   159    // A negation expression swaps the positive and the negative coordinates
   160    // and also negates the constant value.
   161    SDBMBuilderResult visitNeg(SDBMNegExpr expr) {
   162      SDBMBuilderResult result = visit(expr.getVar());
   163      std::swap(result.positivePos, result.negativePos);
   164      result.value = -result.value;
   165      return result;
   166    }
   167  
   168    // The RHS of a sum expression must be a constant and therefore must have both
   169    // positive and negative coordinates at zero.  Take the sum of the values
   170    // between LHS and RHS and keep LHS coordinates.
   171    SDBMBuilderResult visitSum(SDBMSumExpr expr) {
   172      auto lhs = visit(expr.getLHS());
   173      auto rhs = visit(expr.getRHS());
   174      for (auto pos : rhs.negativePos) {
   175        (void)pos;
   176        assert(pos == 0 && "unexpected variable on the RHS of SDBM sum");
   177      }
   178      for (auto pos : rhs.positivePos) {
   179        (void)pos;
   180        assert(pos == 0 && "unexpected variable on the RHS of SDBM sum");
   181      }
   182  
   183      lhs.value += rhs.value;
   184      return lhs;
   185    }
   186  
   187    SDBMBuilder(llvm::DenseMap<SDBMExpr, llvm::SmallVector<unsigned, 2>>
   188                    &pointExprToStripe,
   189                llvm::function_ref<unsigned(SDBMInputExpr)> callback)
   190        : pointExprToStripe(pointExprToStripe), linearPosition(callback) {}
   191  
   192    llvm::DenseMap<SDBMExpr, llvm::SmallVector<unsigned, 2>> &pointExprToStripe;
   193    llvm::function_ref<unsigned(SDBMInputExpr)> linearPosition;
   194  };
   195  } // namespace
   196  
   197  SDBM SDBM::get(ArrayRef<SDBMExpr> inequalities, ArrayRef<SDBMExpr> equalities) {
   198    SDBM result;
   199  
   200    // TODO(zinenko): consider detecting equalities in the list of inequalities.
   201    // This is potentially expensive and requires to
   202    //   - create a list of negated inequalities (may allocate under lock);
   203    //   - perform a pairwise comparison of direct and negated inequalities;
   204    //   - copy the lists of equalities and inequalities, and move entries between
   205    //     them;
   206    // only for the purpose of sparing a temporary variable in cases where an
   207    // implicit equality between a variable and a stripe expression is present in
   208    // the input.
   209  
   210    // Do the first sweep over (in)equalities to collect the information necessary
   211    // to allocate the SDB matrix (number of dimensions, symbol and temporary
   212    // variables required for stripe expressions).
   213    llvm::SmallSetVector<SDBMExpr, 8> stripes;
   214    int maxDim = -1;
   215    int maxSymbol = -1;
   216    for (auto expr : inequalities)
   217      collectSDBMBuildInfo(expr, maxDim, maxSymbol, stripes);
   218    for (auto expr : equalities)
   219      collectSDBMBuildInfo(expr, maxDim, maxSymbol, stripes);
   220    // Indexing of dimensions starts with 0, obtain the number of dimensions by
   221    // incrementing the maximal position of the dimension seen in expressions.
   222    result.numDims = maxDim + 1;
   223    result.numSymbols = maxSymbol + 1;
   224    result.numTemporaries = 0;
   225  
   226    // Helper function that returns the position of the variable represented by
   227    // an SDBM input expression.
   228    auto linearPosition = [result](SDBMInputExpr expr) {
   229      if (expr.isa<SDBMDimExpr>())
   230        return result.getDimPosition(expr.getPosition());
   231      return result.getSymbolPosition(expr.getPosition());
   232    };
   233  
   234    // Check if some stripe expressions are equal to another variable. In
   235    // particular, look for the equalities of the form
   236    //   d0 - stripe-expression = 0, or
   237    //   stripe-expression - d0 = 0.
   238    // There may be multiple variables that are equal to the same stripe
   239    // expression.  Keep track of those in pointExprToStripe.
   240    // There may also be multiple stripe expressions equal to the same variable.
   241    // Introduce a temporary variable for each of those.
   242    llvm::DenseMap<SDBMExpr, llvm::SmallVector<unsigned, 2>> pointExprToStripe;
   243    unsigned numTemporaries = 0;
   244  
   245    auto updateStripePointMaps = [&numTemporaries, &result, &pointExprToStripe,
   246                                  linearPosition](SDBMInputExpr input,
   247                                                  SDBMExpr expr) {
   248      unsigned position = linearPosition(input);
   249      if (result.stripeToPoint.count(position) &&
   250          result.stripeToPoint[position] != expr) {
   251        position = result.getNumVariables() + numTemporaries++;
   252      }
   253      pointExprToStripe[expr].push_back(position);
   254      result.stripeToPoint.insert(std::make_pair(position, expr));
   255    };
   256  
   257    for (auto eq : equalities) {
   258      auto diffExpr = eq.dyn_cast<SDBMDiffExpr>();
   259      if (!diffExpr)
   260        continue;
   261  
   262      auto lhs = diffExpr.getLHS();
   263      auto rhs = diffExpr.getRHS();
   264      auto lhsInput = lhs.dyn_cast<SDBMInputExpr>();
   265      auto rhsInput = rhs.dyn_cast<SDBMInputExpr>();
   266  
   267      if (lhsInput && stripes.count(rhs))
   268        updateStripePointMaps(lhsInput, rhs);
   269      if (rhsInput && stripes.count(lhs))
   270        updateStripePointMaps(rhsInput, lhs);
   271    }
   272  
   273    // Assign the remaining stripe expressions to temporary variables.  These
   274    // expressions are the ones that could not be associated with an existing
   275    // variable in the previous step.
   276    for (auto expr : stripes) {
   277      if (pointExprToStripe.count(expr))
   278        continue;
   279      unsigned position = result.getNumVariables() + numTemporaries++;
   280      pointExprToStripe[expr].push_back(position);
   281      result.stripeToPoint.insert(std::make_pair(position, expr));
   282    }
   283  
   284    // Create the DBM matrix, initialized to infinity values for the least tight
   285    // possible bound (x - y <= infinity is always true).
   286    result.numTemporaries = numTemporaries;
   287    result.matrix.resize(result.getNumVariables() * result.getNumVariables(),
   288                         IntInfty::infinity());
   289  
   290    SDBMBuilder builder(pointExprToStripe, linearPosition);
   291  
   292    // Only keep the tightest constraint.  Since we transform everything into
   293    // less-than-or-equals-to inequalities, keep the smallest constant.  For
   294    // example, if we have d0 - d1 <= 42 and d0 - d1 <= 2, we keep the latter.
   295    // Note that the input expressions are in the shape of d0 - d1 + -42 <= 0
   296    // so we negate the value before storing it.
   297    // In case where the positive and the negative positions are equal, the
   298    // corresponding expression has the form d0 - d0 + -42 <= 0.  If the constant
   299    // value is positive, the set defined by SDBM is trivially empty.  We store
   300    // this value anyway and continue processing to maintain the correspondence
   301    // between the matrix form and the list-of-SDBMExpr form.
   302    // TODO(zinenko): we may want to reconsider this once we have canonicalization
   303    // or simplification in place
   304    auto updateMatrix = [](SDBM &sdbm, const SDBMBuilderResult &r) {
   305      for (auto positivePos : r.positivePos) {
   306        for (auto negativePos : r.negativePos) {
   307          auto &m = sdbm.at(negativePos, positivePos);
   308          m = m < -r.value ? m : -r.value;
   309        }
   310      }
   311    };
   312  
   313    // Do the second sweep on (in)equalities, updating the SDB matrix to reflect
   314    // the constraints.
   315    for (auto ineq : inequalities)
   316      updateMatrix(result, builder.visit(ineq));
   317  
   318    // An equality f(x) = 0 is represented as a pair of inequalities {f(x) >= 0;
   319    // f(x) <= 0} or, alternatively, {-f(x) <= 0 and f(x) <= 0}.
   320    for (auto eq : equalities) {
   321      updateMatrix(result, builder.visit(eq));
   322      updateMatrix(result, builder.visit(-eq));
   323    }
   324  
   325    // Add the inequalities induced by stripe equalities.
   326    //   t = x # C  =>  t <= x <= t + C - 1
   327    // which is equivalent to
   328    //   {t - x <= 0;
   329    //    x - t - (C - 1) <= 0}.
   330    for (const auto &pair : result.stripeToPoint) {
   331      auto stripe = pair.second.cast<SDBMStripeExpr>();
   332      SDBMBuilderResult update = builder.visit(stripe.getVar());
   333      assert(update.negativePos.size() == 1 && update.negativePos[0] == 0 &&
   334             "unexpected negated variable in stripe expression");
   335      assert(update.value == 0 &&
   336             "unexpected non-zero value in stripe expression");
   337      update.negativePos.clear();
   338      update.negativePos.push_back(pair.first);
   339      update.value = -(stripe.getStripeFactor().getValue() - 1);
   340      updateMatrix(result, update);
   341  
   342      std::swap(update.negativePos, update.positivePos);
   343      update.value = 0;
   344      updateMatrix(result, update);
   345    }
   346  
   347    return result;
   348  }
   349  
   350  // Given a row and a column position in the square DBM, insert one equality
   351  // or up to two inequalities that correspond the entries (col, row) and (row,
   352  // col) in the DBM.  `rowExpr` and `colExpr` contain the expressions such that
   353  // colExpr - rowExpr <= V where V is the value at (row, col) in the DBM.
   354  // If one of the expressions is derived from another using a stripe operation,
   355  // check if the inequalities induced by the stripe operation subsume the
   356  // inequalities defined in the DBM and if so, elide these inequalities.
   357  void SDBM::convertDBMElement(unsigned row, unsigned col,
   358                               SDBMPositiveExpr rowExpr, SDBMPositiveExpr colExpr,
   359                               SmallVectorImpl<SDBMExpr> &inequalities,
   360                               SmallVectorImpl<SDBMExpr> &equalities) {
   361    using ops_assertions::operator+;
   362    using ops_assertions::operator-;
   363  
   364    auto diffIJValue = at(col, row);
   365    auto diffJIValue = at(row, col);
   366  
   367    // If symmetric entries are opposite, the corresponding expressions are equal.
   368    if (diffIJValue.isFinite() &&
   369        diffIJValue.getValue() == -diffJIValue.getValue()) {
   370      equalities.push_back(rowExpr - colExpr - diffIJValue.getValue());
   371      return;
   372    }
   373  
   374    // Given an inequality x0 - x1 <= A, check if x0 is a stripe variable derived
   375    // from x1: x0 = x1 # B.  If so, it would imply the constraints
   376    // x0 <= x1 <= x0 + (B - 1) <=> x0 - x1 <= 0 and x1 - x0 <= (B - 1).
   377    // Therefore, if A >= 0, this inequality is subsumed by that implied
   378    // by the stripe equality and thus can be elided.
   379    // Similarly, check if x1 is a stripe variable derived from x0: x1 = x0 # C.
   380    // If so, it would imply the constraints x1 <= x0 <= x1 + (C - 1) <=>
   381    // <=> x1 - x0 <= 0 and x0 - x1 <= (C - 1).  Therefore, if A >= (C - 1), this
   382    // inequality can be elided.
   383    //
   384    // Note: x0 and x1 may be a stripe expressions themselves, we rely on stripe
   385    // expressions being stored without temporaries on the RHS and being passed
   386    // into this function as is.
   387    auto canElide = [this](unsigned x0, unsigned x1, SDBMExpr x0Expr,
   388                           SDBMExpr x1Expr, int64_t value) {
   389      if (stripeToPoint.count(x0)) {
   390        auto stripe = stripeToPoint[x0].cast<SDBMStripeExpr>();
   391        SDBMPositiveExpr var = stripe.getVar();
   392        if (x1Expr == var && value >= 0)
   393          return true;
   394      }
   395      if (stripeToPoint.count(x1)) {
   396        auto stripe = stripeToPoint[x1].cast<SDBMStripeExpr>();
   397        SDBMPositiveExpr var = stripe.getVar();
   398        if (x0Expr == var && value >= stripe.getStripeFactor().getValue() - 1)
   399          return true;
   400      }
   401      return false;
   402    };
   403  
   404    // Check row - col.
   405    if (diffIJValue.isFinite() &&
   406        !canElide(row, col, rowExpr, colExpr, diffIJValue.getValue())) {
   407      inequalities.push_back(rowExpr - colExpr - diffIJValue.getValue());
   408    }
   409    // Check col - row.
   410    if (diffJIValue.isFinite() &&
   411        !canElide(col, row, colExpr, rowExpr, diffJIValue.getValue())) {
   412      inequalities.push_back(colExpr - rowExpr - diffJIValue.getValue());
   413    }
   414  }
   415  
   416  // The values on the main diagonal correspond to the upper bound on the
   417  // difference between a variable and itself: d0 - d0 <= C, or alternatively
   418  // to -C <= 0.  Only construct the inequalities when C is negative, which
   419  // are trivially false but necessary for the returned system of inequalities
   420  // to indicate that the set it defines is empty.
   421  void SDBM::convertDBMDiagonalElement(unsigned pos, SDBMPositiveExpr expr,
   422                                       SmallVectorImpl<SDBMExpr> &inequalities) {
   423    auto selfDifference = at(pos, pos);
   424    if (selfDifference.isFinite() && selfDifference < 0) {
   425      auto selfDifferenceValueExpr =
   426          SDBMConstantExpr::get(expr.getDialect(), -selfDifference.getValue());
   427      inequalities.push_back(selfDifferenceValueExpr);
   428    }
   429  }
   430  
   431  void SDBM::getSDBMExpressions(SDBMDialect *dialect,
   432                                SmallVectorImpl<SDBMExpr> &inequalities,
   433                                SmallVectorImpl<SDBMExpr> &equalities) {
   434    using ops_assertions::operator-;
   435    using ops_assertions::operator+;
   436  
   437    // Helper function that creates an SDBMInputExpr given the linearized position
   438    // of variable in the DBM.
   439    auto getInput = [dialect, this](unsigned matrixPos) -> SDBMInputExpr {
   440      if (matrixPos < numDims)
   441        return SDBMDimExpr::get(dialect, matrixPos);
   442      return SDBMSymbolExpr::get(dialect, matrixPos - numDims);
   443    };
   444  
   445    // The top-left value corresponds to inequality 0 <= C.  If C is negative, the
   446    // set defined by SDBM is trivially empty and we add the constraint -C <= 0 to
   447    // the list of inequalities.  Otherwise, the constraint is trivially true and
   448    // we ignore it.
   449    auto difference = at(0, 0);
   450    if (difference.isFinite() && difference < 0) {
   451      inequalities.push_back(
   452          SDBMConstantExpr::get(dialect, -difference.getValue()));
   453    }
   454  
   455    // Traverse the segment of the matrix that involves non-temporary variables.
   456    unsigned numTrueVariables = numDims + numSymbols;
   457    for (unsigned i = 0; i < numTrueVariables; ++i) {
   458      // The first row and column represent numerical upper and lower bound on
   459      // each variable.  Transform them into inequalities if they are finite.
   460      auto upperBound = at(0, 1 + i);
   461      auto lowerBound = at(1 + i, 0);
   462      auto inputExpr = getInput(i);
   463      if (upperBound.isFinite() &&
   464          upperBound.getValue() == -lowerBound.getValue()) {
   465        equalities.push_back(inputExpr - upperBound.getValue());
   466      } else if (upperBound.isFinite()) {
   467        inequalities.push_back(inputExpr - upperBound.getValue());
   468      } else if (lowerBound.isFinite()) {
   469        inequalities.push_back(-inputExpr - lowerBound.getValue());
   470      }
   471  
   472      // Introduce trivially false inequalities if required by diagonal elements.
   473      convertDBMDiagonalElement(1 + i, inputExpr, inequalities);
   474  
   475      // Introduce equalities or inequalities between non-temporary variables.
   476      for (unsigned j = 0; j < i; ++j) {
   477        convertDBMElement(1 + i, 1 + j, getInput(i), getInput(j), inequalities,
   478                          equalities);
   479      }
   480    }
   481  
   482    // Add equalities for stripe expressions that define non-temporary
   483    // variables.  Temporary variables will be substituted into their uses and
   484    // should not appear in the resulting equalities.
   485    for (const auto &stripePair : stripeToPoint) {
   486      unsigned position = stripePair.first;
   487      if (position < 1 + numTrueVariables) {
   488        equalities.push_back(getInput(position - 1) - stripePair.second);
   489      }
   490    }
   491  
   492    // Add equalities / inequalities involving temporaries by replacing the
   493    // temporaries with stripe expressions that define them.
   494    for (unsigned i = 1 + numTrueVariables, e = getNumVariables(); i < e; ++i) {
   495      // Mixed constraints involving one temporary (j) and one non-temporary (i)
   496      // variable.
   497      for (unsigned j = 0; j < numTrueVariables; ++j) {
   498        convertDBMElement(i, 1 + j, stripeToPoint[i].cast<SDBMStripeExpr>(),
   499                          getInput(j), inequalities, equalities);
   500      }
   501  
   502      // Constraints involving only temporary variables.
   503      for (unsigned j = 1 + numTrueVariables; j < i; ++j) {
   504        convertDBMElement(i, j, stripeToPoint[i].cast<SDBMStripeExpr>(),
   505                          stripeToPoint[j].cast<SDBMStripeExpr>(), inequalities,
   506                          equalities);
   507      }
   508  
   509      // Introduce trivially false inequalities if required by diagonal elements.
   510      convertDBMDiagonalElement(i, stripeToPoint[i].cast<SDBMStripeExpr>(),
   511                                inequalities);
   512    }
   513  }
   514  
   515  void SDBM::print(llvm::raw_ostream &os) {
   516    unsigned numVariables = getNumVariables();
   517  
   518    // Helper function that prints the name of the variable given its linearized
   519    // position in the DBM.
   520    auto getVarName = [this](unsigned matrixPos) -> std::string {
   521      if (matrixPos == 0)
   522        return "cst";
   523      matrixPos -= 1;
   524      if (matrixPos < numDims)
   525        return llvm::formatv("d{0}", matrixPos);
   526      matrixPos -= numDims;
   527      if (matrixPos < numSymbols)
   528        return llvm::formatv("s{0}", matrixPos);
   529      matrixPos -= numSymbols;
   530      return llvm::formatv("t{0}", matrixPos);
   531    };
   532  
   533    // Header row.
   534    os << "      cst";
   535    for (unsigned i = 1; i < numVariables; ++i) {
   536      os << llvm::formatv(" {0,4}", getVarName(i));
   537    }
   538    os << '\n';
   539  
   540    // Data rows.
   541    for (unsigned i = 0; i < numVariables; ++i) {
   542      os << llvm::formatv("{0,-4}", getVarName(i));
   543      for (unsigned j = 0; j < numVariables; ++j) {
   544        IntInfty value = operator()(i, j);
   545        if (!value.isFinite())
   546          os << "  inf";
   547        else
   548          os << llvm::formatv(" {0,4}", value.getValue());
   549      }
   550      os << '\n';
   551    }
   552  
   553    // Explanation of temporaries.
   554    for (const auto &pair : stripeToPoint) {
   555      os << getVarName(pair.first) << " = ";
   556      pair.second.print(os);
   557      os << '\n';
   558    }
   559  }
   560  
   561  void SDBM::dump() { print(llvm::errs()); }