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()); }