1 //===- PresburgerRelation.cpp - MLIR PresburgerRelation Class -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "mlir/Analysis/Presburger/PresburgerRelation.h" 10 #include "mlir/Analysis/Presburger/Simplex.h" 11 #include "mlir/Analysis/Presburger/Utils.h" 12 #include "llvm/ADT/STLExtras.h" 13 #include "llvm/ADT/ScopeExit.h" 14 #include "llvm/ADT/SmallBitVector.h" 15 16 using namespace mlir; 17 using namespace presburger; 18 19 PresburgerRelation::PresburgerRelation(const IntegerRelation &disjunct) 20 : space(disjunct.getSpaceWithoutLocals()) { 21 unionInPlace(disjunct); 22 } 23 24 unsigned PresburgerRelation::getNumDisjuncts() const { 25 return disjuncts.size(); 26 } 27 28 ArrayRef<IntegerRelation> PresburgerRelation::getAllDisjuncts() const { 29 return disjuncts; 30 } 31 32 const IntegerRelation &PresburgerRelation::getDisjunct(unsigned index) const { 33 assert(index < disjuncts.size() && "index out of bounds!"); 34 return disjuncts[index]; 35 } 36 37 /// Mutate this set, turning it into the union of this set and the given 38 /// IntegerRelation. 39 void PresburgerRelation::unionInPlace(const IntegerRelation &disjunct) { 40 assert(space.isCompatible(disjunct.getSpace()) && "Spaces should match"); 41 disjuncts.push_back(disjunct); 42 } 43 44 /// Mutate this set, turning it into the union of this set and the given set. 45 /// 46 /// This is accomplished by simply adding all the disjuncts of the given set 47 /// to this set. 48 void PresburgerRelation::unionInPlace(const PresburgerRelation &set) { 49 assert(space.isCompatible(set.getSpace()) && "Spaces should match"); 50 for (const IntegerRelation &disjunct : set.disjuncts) 51 unionInPlace(disjunct); 52 } 53 54 /// Return the union of this set and the given set. 55 PresburgerRelation 56 PresburgerRelation::unionSet(const PresburgerRelation &set) const { 57 assert(space.isCompatible(set.getSpace()) && "Spaces should match"); 58 PresburgerRelation result = *this; 59 result.unionInPlace(set); 60 return result; 61 } 62 63 /// A point is contained in the union iff any of the parts contain the point. 64 bool PresburgerRelation::containsPoint(ArrayRef<int64_t> point) const { 65 return llvm::any_of(disjuncts, [&](const IntegerRelation &disjunct) { 66 return (disjunct.containsPointNoLocal(point)); 67 }); 68 } 69 70 PresburgerRelation 71 PresburgerRelation::getUniverse(const PresburgerSpace &space) { 72 PresburgerRelation result(space); 73 result.unionInPlace(IntegerRelation::getUniverse(space)); 74 return result; 75 } 76 77 PresburgerRelation PresburgerRelation::getEmpty(const PresburgerSpace &space) { 78 return PresburgerRelation(space); 79 } 80 81 // Return the intersection of this set with the given set. 82 // 83 // We directly compute (S_1 or S_2 ...) and (T_1 or T_2 ...) 84 // as (S_1 and T_1) or (S_1 and T_2) or ... 85 // 86 // If S_i or T_j have local variables, then S_i and T_j contains the local 87 // variables of both. 88 PresburgerRelation 89 PresburgerRelation::intersect(const PresburgerRelation &set) const { 90 assert(space.isCompatible(set.getSpace()) && "Spaces should match"); 91 92 PresburgerRelation result(getSpace()); 93 for (const IntegerRelation &csA : disjuncts) { 94 for (const IntegerRelation &csB : set.disjuncts) { 95 IntegerRelation intersection = csA.intersect(csB); 96 if (!intersection.isEmpty()) 97 result.unionInPlace(intersection); 98 } 99 } 100 return result; 101 } 102 103 /// Return the coefficients of the ineq in `rel` specified by `idx`. 104 /// `idx` can refer not only to an actual inequality of `rel`, but also 105 /// to either of the inequalities that make up an equality in `rel`. 106 /// 107 /// When 0 <= idx < rel.getNumInequalities(), this returns the coeffs of the 108 /// idx-th inequality of `rel`. 109 /// 110 /// Otherwise, it is then considered to index into the ineqs corresponding to 111 /// eqs of `rel`, and it must hold that 112 /// 113 /// 0 <= idx - rel.getNumInequalities() < 2*getNumEqualities(). 114 /// 115 /// For every eq `coeffs == 0` there are two possible ineqs to index into. 116 /// The first is coeffs >= 0 and the second is coeffs <= 0. 117 static SmallVector<int64_t, 8> getIneqCoeffsFromIdx(const IntegerRelation &rel, 118 unsigned idx) { 119 assert(idx < rel.getNumInequalities() + 2 * rel.getNumEqualities() && 120 "idx out of bounds!"); 121 if (idx < rel.getNumInequalities()) 122 return llvm::to_vector<8>(rel.getInequality(idx)); 123 124 idx -= rel.getNumInequalities(); 125 ArrayRef<int64_t> eqCoeffs = rel.getEquality(idx / 2); 126 127 if (idx % 2 == 0) 128 return llvm::to_vector<8>(eqCoeffs); 129 return getNegatedCoeffs(eqCoeffs); 130 } 131 132 /// Return the set difference b \ s. 133 /// 134 /// In the following, U denotes union, /\ denotes intersection, \ denotes set 135 /// difference and ~ denotes complement. 136 /// 137 /// Let s = (U_i s_i). We want b \ (U_i s_i). 138 /// 139 /// Let s_i = /\_j s_ij, where each s_ij is a single inequality. To compute 140 /// b \ s_i = b /\ ~s_i, we partition s_i based on the first violated 141 /// inequality: ~s_i = (~s_i1) U (s_i1 /\ ~s_i2) U (s_i1 /\ s_i2 /\ ~s_i3) U ... 142 /// And the required result is (b /\ ~s_i1) U (b /\ s_i1 /\ ~s_i2) U ... 143 /// We recurse by subtracting U_{j > i} S_j from each of these parts and 144 /// returning the union of the results. Each equality is handled as a 145 /// conjunction of two inequalities. 146 /// 147 /// Note that the same approach works even if an inequality involves a floor 148 /// division. For example, the complement of x <= 7*floor(x/7) is still 149 /// x > 7*floor(x/7). Since b \ s_i contains the inequalities of both b and s_i 150 /// (or the complements of those inequalities), b \ s_i may contain the 151 /// divisions present in both b and s_i. Therefore, we need to add the local 152 /// division variables of both b and s_i to each part in the result. This means 153 /// adding the local variables of both b and s_i, as well as the corresponding 154 /// division inequalities to each part. Since the division inequalities are 155 /// added to each part, we can skip the parts where the complement of any 156 /// division inequality is added, as these parts will become empty anyway. 157 /// 158 /// As a heuristic, we try adding all the constraints and check if simplex 159 /// says that the intersection is empty. If it is, then subtracting this 160 /// disjuncts is a no-op and we just skip it. Also, in the process we find out 161 /// that some constraints are redundant. These redundant constraints are 162 /// ignored. 163 /// 164 static PresburgerRelation getSetDifference(IntegerRelation b, 165 const PresburgerRelation &s) { 166 assert(b.getSpace().isCompatible(s.getSpace()) && "Spaces should match"); 167 if (b.isEmptyByGCDTest()) 168 return PresburgerRelation::getEmpty(b.getSpaceWithoutLocals()); 169 170 // Remove duplicate divs up front here to avoid existing 171 // divs disappearing in the call to mergeLocalIds below. 172 b.removeDuplicateDivs(); 173 174 PresburgerRelation result = 175 PresburgerRelation::getEmpty(b.getSpaceWithoutLocals()); 176 Simplex simplex(b); 177 178 // This algorithm is more naturally expressed recursively, but we implement 179 // it iteratively here to avoid issues with stack sizes. 180 // 181 // Each level of the recursion has five stack variables. 182 struct Frame { 183 // A snapshot of the simplex state to rollback to. 184 unsigned simplexSnapshot; 185 // A CountsSnapshot of `b` to rollback to. 186 IntegerRelation::CountsSnapshot bCounts; 187 // The IntegerRelation currently being operated on. 188 IntegerRelation sI; 189 // A list of indexes (see getIneqCoeffsFromIdx) of inequalities to be 190 // processed. 191 SmallVector<unsigned, 8> ineqsToProcess; 192 // The index of the last inequality that was processed at this level. 193 // This is empty when we are coming to this level for the first time. 194 Optional<unsigned> lastIneqProcessed; 195 }; 196 SmallVector<Frame, 2> frames; 197 198 // When we "recurse", we ensure the current frame is stored in `frames` and 199 // increment `level`. When we return, we decrement `level`. 200 unsigned level = 1; 201 while (level > 0) { 202 if (level - 1 >= s.getNumDisjuncts()) { 203 // No more parts to subtract; add to the result and return. 204 result.unionInPlace(b); 205 level = frames.size(); 206 continue; 207 } 208 209 if (level > frames.size()) { 210 // No frame for this level yet, so we have just recursed into this level. 211 IntegerRelation sI = s.getDisjunct(level - 1); 212 // Remove the duplicate divs up front to avoid them possibly disappearing 213 // in the call to mergeLocalIds below. 214 sI.removeDuplicateDivs(); 215 216 // Below, we append some additional constraints and ids to b. We want to 217 // rollback b to its initial state before returning, which we will do by 218 // removing all constraints beyond the original number of inequalities 219 // and equalities, so we store these counts first. 220 IntegerRelation::CountsSnapshot initBCounts = b.getCounts(); 221 // Similarly, we also want to rollback simplex to its original state. 222 unsigned initialSnapshot = simplex.getSnapshot(); 223 224 // Find out which inequalities of sI correspond to division inequalities 225 // for the local variables of sI. 226 std::vector<MaybeLocalRepr> repr(sI.getNumLocalIds()); 227 sI.getLocalReprs(repr); 228 229 // Add sI's locals to b, after b's locals. Only those locals of sI which 230 // do not already exist in b will be added. (i.e., duplicate divisions 231 // will not be added.) Also add b's locals to sI, in such a way that both 232 // have the same locals in the same order in the end. 233 b.mergeLocalIds(sI); 234 235 // Mark which inequalities of sI are division inequalities and add all 236 // such inequalities to b. 237 llvm::SmallBitVector canIgnoreIneq(sI.getNumInequalities() + 238 2 * sI.getNumEqualities()); 239 for (MaybeLocalRepr &maybeRepr : repr) { 240 assert( 241 maybeRepr && 242 "Subtraction is not supported when a representation of the local " 243 "variables of the subtrahend cannot be found!"); 244 245 if (maybeRepr.kind == ReprKind::Inequality) { 246 unsigned lb = maybeRepr.repr.inequalityPair.lowerBoundIdx; 247 unsigned ub = maybeRepr.repr.inequalityPair.upperBoundIdx; 248 249 b.addInequality(sI.getInequality(lb)); 250 b.addInequality(sI.getInequality(ub)); 251 252 assert(lb != ub && 253 "Upper and lower bounds must be different inequalities!"); 254 canIgnoreIneq[lb] = true; 255 canIgnoreIneq[ub] = true; 256 } else { 257 assert(maybeRepr.kind == ReprKind::Equality && 258 "ReprKind isn't inequality so should be equality"); 259 unsigned idx = maybeRepr.repr.equalityIdx; 260 b.addEquality(sI.getEquality(idx)); 261 // We can ignore both inequalities corresponding to this equality. 262 unsigned offset = sI.getNumInequalities(); 263 canIgnoreIneq[offset + 2 * idx] = true; 264 canIgnoreIneq[offset + 2 * idx + 1] = true; 265 } 266 } 267 268 unsigned offset = simplex.getNumConstraints(); 269 unsigned numLocalsAdded = 270 b.getNumLocalIds() - initBCounts.getSpace().getNumLocalIds(); 271 simplex.appendVariable(numLocalsAdded); 272 273 unsigned snapshotBeforeIntersect = simplex.getSnapshot(); 274 simplex.intersectIntegerRelation(sI); 275 276 if (simplex.isEmpty()) { 277 // b /\ s_i is empty, so b \ s_i = b. We move directly to i + 1. 278 // We are ignoring level i completely, so we restore the state 279 // *before* going to the next level. 280 b.truncate(initBCounts); 281 simplex.rollback(initialSnapshot); 282 // Recurse. We haven't processed any inequalities and 283 // we don't need to process anything when we return. 284 // 285 // TODO: consider supporting tail recursion directly if this becomes 286 // relevant for performance. 287 frames.push_back(Frame{initialSnapshot, initBCounts, sI, 288 /*ineqsToProcess=*/{}, 289 /*lastIneqProcessed=*/{}}); 290 ++level; 291 continue; 292 } 293 294 // Equalities are added to simplex as a pair of inequalities. 295 unsigned totalNewSimplexInequalities = 296 2 * sI.getNumEqualities() + sI.getNumInequalities(); 297 // Look for redundant constraints among the constraints of sI. We don't 298 // care about redundant constraints in `b` at this point. 299 // 300 // When there are two copies of a constraint in `simplex`, i.e., among the 301 // constraints of `b` and `sI`, only one of them can be marked redundant. 302 // (Assuming no other constraint makes these redundant.) 303 // 304 // In a case where there is one copy in `b` and one in `sI`, we want the 305 // one in `sI` to be marked, not the one in `b`. Therefore, it's not 306 // enough to ignore the constraints of `b` when checking which 307 // constraints `detectRedundant` has marked redundant; we explicitly tell 308 // `detectRedundant` to only mark constraints from `sI` as being 309 // redundant. 310 simplex.detectRedundant(offset, totalNewSimplexInequalities); 311 for (unsigned j = 0; j < totalNewSimplexInequalities; j++) 312 canIgnoreIneq[j] = simplex.isMarkedRedundant(offset + j); 313 simplex.rollback(snapshotBeforeIntersect); 314 315 SmallVector<unsigned, 8> ineqsToProcess; 316 ineqsToProcess.reserve(totalNewSimplexInequalities); 317 for (unsigned i = 0; i < totalNewSimplexInequalities; ++i) 318 if (!canIgnoreIneq[i]) 319 ineqsToProcess.push_back(i); 320 321 if (ineqsToProcess.empty()) { 322 // Nothing to process; return. (we have no frame to pop.) 323 level = frames.size(); 324 continue; 325 } 326 327 unsigned simplexSnapshot = simplex.getSnapshot(); 328 IntegerRelation::CountsSnapshot bCounts = b.getCounts(); 329 frames.push_back(Frame{simplexSnapshot, bCounts, sI, ineqsToProcess, 330 /*lastIneqProcessed=*/llvm::None}); 331 // We have completed the initial setup for this level. 332 // Fallthrough to the main recursive part below. 333 } 334 335 // For each inequality ineq, we first recurse with the part where ineq 336 // is not satisfied, and then add ineq to b and simplex because 337 // ineq must be satisfied by all later parts. 338 if (level == frames.size()) { 339 Frame &frame = frames.back(); 340 if (frame.lastIneqProcessed) { 341 // Let the current value of b be b' and 342 // let the initial value of b when we first came to this level be b. 343 // 344 // b' is equal to b /\ s_i1 /\ s_i2 /\ ... /\ s_i{j-1} /\ ~s_ij. 345 // We had previously recursed with the part where s_ij was not 346 // satisfied; all further parts satisfy s_ij, so we rollback to the 347 // state before adding this complement constraint, and add s_ij to b. 348 simplex.rollback(frame.simplexSnapshot); 349 b.truncate(frame.bCounts); 350 SmallVector<int64_t, 8> ineq = 351 getIneqCoeffsFromIdx(frame.sI, *frame.lastIneqProcessed); 352 b.addInequality(ineq); 353 simplex.addInequality(ineq); 354 } 355 356 if (frame.ineqsToProcess.empty()) { 357 // No ineqs left to process; pop this level's frame and return. 358 frames.pop_back(); 359 level = frames.size(); 360 continue; 361 } 362 363 // "Recurse" with the part where the ineq is not satisfied. 364 frame.bCounts = b.getCounts(); 365 frame.simplexSnapshot = simplex.getSnapshot(); 366 367 unsigned idx = frame.ineqsToProcess.back(); 368 SmallVector<int64_t, 8> ineq = 369 getComplementIneq(getIneqCoeffsFromIdx(frame.sI, idx)); 370 b.addInequality(ineq); 371 simplex.addInequality(ineq); 372 373 frame.ineqsToProcess.pop_back(); 374 frame.lastIneqProcessed = idx; 375 ++level; 376 continue; 377 } 378 } 379 380 return result; 381 } 382 383 /// Return the complement of this set. 384 PresburgerRelation PresburgerRelation::complement() const { 385 return getSetDifference(IntegerRelation::getUniverse(getSpace()), *this); 386 } 387 388 /// Return the result of subtract the given set from this set, i.e., 389 /// return `this \ set`. 390 PresburgerRelation 391 PresburgerRelation::subtract(const PresburgerRelation &set) const { 392 assert(space.isCompatible(set.getSpace()) && "Spaces should match"); 393 PresburgerRelation result(getSpace()); 394 // We compute (U_i t_i) \ (U_i set_i) as U_i (t_i \ V_i set_i). 395 for (const IntegerRelation &disjunct : disjuncts) 396 result.unionInPlace(getSetDifference(disjunct, set)); 397 return result; 398 } 399 400 /// T is a subset of S iff T \ S is empty, since if T \ S contains a 401 /// point then this is a point that is contained in T but not S, and 402 /// if T contains a point that is not in S, this also lies in T \ S. 403 bool PresburgerRelation::isSubsetOf(const PresburgerRelation &set) const { 404 return this->subtract(set).isIntegerEmpty(); 405 } 406 407 /// Two sets are equal iff they are subsets of each other. 408 bool PresburgerRelation::isEqual(const PresburgerRelation &set) const { 409 assert(space.isCompatible(set.getSpace()) && "Spaces should match"); 410 return this->isSubsetOf(set) && set.isSubsetOf(*this); 411 } 412 413 /// Return true if all the sets in the union are known to be integer empty, 414 /// false otherwise. 415 bool PresburgerRelation::isIntegerEmpty() const { 416 // The set is empty iff all of the disjuncts are empty. 417 return llvm::all_of(disjuncts, std::mem_fn(&IntegerRelation::isIntegerEmpty)); 418 } 419 420 bool PresburgerRelation::findIntegerSample(SmallVectorImpl<int64_t> &sample) { 421 // A sample exists iff any of the disjuncts contains a sample. 422 for (const IntegerRelation &disjunct : disjuncts) { 423 if (Optional<SmallVector<int64_t, 8>> opt = disjunct.findIntegerSample()) { 424 sample = std::move(*opt); 425 return true; 426 } 427 } 428 return false; 429 } 430 431 Optional<uint64_t> PresburgerRelation::computeVolume() const { 432 assert(getNumSymbolIds() == 0 && "Symbols are not yet supported!"); 433 // The sum of the volumes of the disjuncts is a valid overapproximation of the 434 // volume of their union, even if they overlap. 435 uint64_t result = 0; 436 for (const IntegerRelation &disjunct : disjuncts) { 437 Optional<uint64_t> volume = disjunct.computeVolume(); 438 if (!volume) 439 return {}; 440 result += *volume; 441 } 442 return result; 443 } 444 445 /// The SetCoalescer class contains all functionality concerning the coalesce 446 /// heuristic. It is built from a `PresburgerRelation` and has the `coalesce()` 447 /// function as its main API. The coalesce heuristic simplifies the 448 /// representation of a PresburgerRelation. In particular, it removes all 449 /// disjuncts which are subsets of other disjuncts in the union and it combines 450 /// sets that overlap and can be combined in a convex way. 451 class presburger::SetCoalescer { 452 453 public: 454 /// Simplifies the representation of a PresburgerSet. 455 PresburgerRelation coalesce(); 456 457 /// Construct a SetCoalescer from a PresburgerSet. 458 SetCoalescer(const PresburgerRelation &s); 459 460 private: 461 /// The space of the set the SetCoalescer is coalescing. 462 PresburgerSpace space; 463 464 /// The current list of `IntegerRelation`s that the currently coalesced set is 465 /// the union of. 466 SmallVector<IntegerRelation, 2> disjuncts; 467 /// The list of `Simplex`s constructed from the elements of `disjuncts`. 468 SmallVector<Simplex, 2> simplices; 469 470 /// The list of all inversed equalities during typing. This ensures that 471 /// the constraints exist even after the typing function has concluded. 472 SmallVector<SmallVector<int64_t, 2>, 2> negEqs; 473 474 /// `redundantIneqsA` is the inequalities of `a` that are redundant for `b` 475 /// (similarly for `cuttingIneqsA`, `redundantIneqsB`, and `cuttingIneqsB`). 476 SmallVector<ArrayRef<int64_t>, 2> redundantIneqsA; 477 SmallVector<ArrayRef<int64_t>, 2> cuttingIneqsA; 478 479 SmallVector<ArrayRef<int64_t>, 2> redundantIneqsB; 480 SmallVector<ArrayRef<int64_t>, 2> cuttingIneqsB; 481 482 /// Given a Simplex `simp` and one of its inequalities `ineq`, check 483 /// that the facet of `simp` where `ineq` holds as an equality is contained 484 /// within `a`. 485 bool isFacetContained(ArrayRef<int64_t> ineq, Simplex &simp); 486 487 /// Removes redundant constraints from `disjunct`, adds it to `disjuncts` and 488 /// removes the disjuncts at position `i` and `j`. Updates `simplices` to 489 /// reflect the changes. `i` and `j` cannot be equal. 490 void addCoalescedDisjunct(unsigned i, unsigned j, 491 const IntegerRelation &disjunct); 492 493 /// Checks whether `a` and `b` can be combined in a convex sense, if there 494 /// exist cutting inequalities. 495 /// 496 /// An example of this case: 497 /// ___________ ___________ 498 /// / / | / / / 499 /// \ \ | / ==> \ / 500 /// \ \ | / \ / 501 /// \___\|/ \_____/ 502 /// 503 /// 504 LogicalResult coalescePairCutCase(unsigned i, unsigned j); 505 506 /// Types the inequality `ineq` according to its `IneqType` for `simp` into 507 /// `redundantIneqsB` and `cuttingIneqsB`. Returns success, if no separate 508 /// inequalities were encountered. Otherwise, returns failure. 509 LogicalResult typeInequality(ArrayRef<int64_t> ineq, Simplex &simp); 510 511 /// Types the equality `eq`, i.e. for `eq` == 0, types both `eq` >= 0 and 512 /// -`eq` >= 0 according to their `IneqType` for `simp` into 513 /// `redundantIneqsB` and `cuttingIneqsB`. Returns success, if no separate 514 /// inequalities were encountered. Otherwise, returns failure. 515 LogicalResult typeEquality(ArrayRef<int64_t> eq, Simplex &simp); 516 517 /// Replaces the element at position `i` with the last element and erases 518 /// the last element for both `disjuncts` and `simplices`. 519 void eraseDisjunct(unsigned i); 520 521 /// Attempts to coalesce the two IntegerRelations at position `i` and `j` 522 /// in `disjuncts` in-place. Returns whether the disjuncts were 523 /// successfully coalesced. The simplices in `simplices` need to be the ones 524 /// constructed from `disjuncts`. At this point, there are no empty 525 /// disjuncts in `disjuncts` left. 526 LogicalResult coalescePair(unsigned i, unsigned j); 527 }; 528 529 /// Constructs a `SetCoalescer` from a `PresburgerRelation`. Only adds non-empty 530 /// `IntegerRelation`s to the `disjuncts` vector. 531 SetCoalescer::SetCoalescer(const PresburgerRelation &s) : space(s.getSpace()) { 532 533 disjuncts = s.disjuncts; 534 535 simplices.reserve(s.getNumDisjuncts()); 536 // Note that disjuncts.size() changes during the loop. 537 for (unsigned i = 0; i < disjuncts.size();) { 538 disjuncts[i].removeRedundantConstraints(); 539 Simplex simp(disjuncts[i]); 540 if (simp.isEmpty()) { 541 disjuncts[i] = disjuncts[disjuncts.size() - 1]; 542 disjuncts.pop_back(); 543 continue; 544 } 545 ++i; 546 simplices.push_back(simp); 547 } 548 } 549 550 /// Simplifies the representation of a PresburgerSet. 551 PresburgerRelation SetCoalescer::coalesce() { 552 // For all tuples of IntegerRelations, check whether they can be 553 // coalesced. When coalescing is successful, the contained IntegerRelation 554 // is swapped with the last element of `disjuncts` and subsequently erased 555 // and similarly for simplices. 556 for (unsigned i = 0; i < disjuncts.size();) { 557 558 // TODO: This does some comparisons two times (index 0 with 1 and index 1 559 // with 0). 560 bool broken = false; 561 for (unsigned j = 0, e = disjuncts.size(); j < e; ++j) { 562 negEqs.clear(); 563 redundantIneqsA.clear(); 564 redundantIneqsB.clear(); 565 cuttingIneqsA.clear(); 566 cuttingIneqsB.clear(); 567 if (i == j) 568 continue; 569 if (coalescePair(i, j).succeeded()) { 570 broken = true; 571 break; 572 } 573 } 574 575 // Only if the inner loop was not broken, i is incremented. This is 576 // required as otherwise, if a coalescing occurs, the IntegerRelation 577 // now at position i is not compared. 578 if (!broken) 579 ++i; 580 } 581 582 PresburgerRelation newSet = PresburgerRelation::getEmpty(space); 583 for (unsigned i = 0, e = disjuncts.size(); i < e; ++i) 584 newSet.unionInPlace(disjuncts[i]); 585 586 return newSet; 587 } 588 589 /// Given a Simplex `simp` and one of its inequalities `ineq`, check 590 /// that all inequalities of `cuttingIneqsB` are redundant for the facet of 591 /// `simp` where `ineq` holds as an equality is contained within `a`. 592 bool SetCoalescer::isFacetContained(ArrayRef<int64_t> ineq, Simplex &simp) { 593 SimplexRollbackScopeExit scopeExit(simp); 594 simp.addEquality(ineq); 595 return llvm::all_of(cuttingIneqsB, [&simp](ArrayRef<int64_t> curr) { 596 return simp.isRedundantInequality(curr); 597 }); 598 } 599 600 void SetCoalescer::addCoalescedDisjunct(unsigned i, unsigned j, 601 const IntegerRelation &disjunct) { 602 assert(i != j && "The indices must refer to different disjuncts"); 603 unsigned n = disjuncts.size(); 604 if (j == n - 1) { 605 // This case needs special handling since position `n` - 1 is removed 606 // from the vector, hence the `IntegerRelation` at position `n` - 2 is 607 // lost otherwise. 608 disjuncts[i] = disjuncts[n - 2]; 609 disjuncts.pop_back(); 610 disjuncts[n - 2] = disjunct; 611 disjuncts[n - 2].removeRedundantConstraints(); 612 613 simplices[i] = simplices[n - 2]; 614 simplices.pop_back(); 615 simplices[n - 2] = Simplex(disjuncts[n - 2]); 616 617 } else { 618 // Other possible edge cases are correct since for `j` or `i` == `n` - 619 // 2, the `IntegerRelation` at position `n` - 2 should be lost. The 620 // case `i` == `n` - 1 makes the first following statement a noop. 621 // Hence, in this case the same thing is done as above, but with `j` 622 // rather than `i`. 623 disjuncts[i] = disjuncts[n - 1]; 624 disjuncts[j] = disjuncts[n - 2]; 625 disjuncts.pop_back(); 626 disjuncts[n - 2] = disjunct; 627 disjuncts[n - 2].removeRedundantConstraints(); 628 629 simplices[i] = simplices[n - 1]; 630 simplices[j] = simplices[n - 2]; 631 simplices.pop_back(); 632 simplices[n - 2] = Simplex(disjuncts[n - 2]); 633 } 634 } 635 636 /// Given two polyhedra `a` and `b` at positions `i` and `j` in 637 /// `disjuncts` and `redundantIneqsA` being the inequalities of `a` that 638 /// are redundant for `b` (similarly for `cuttingIneqsA`, `redundantIneqsB`, 639 /// and `cuttingIneqsB`), Checks whether the facets of all cutting 640 /// inequalites of `a` are contained in `b`. If so, a new polyhedron 641 /// consisting of all redundant inequalites of `a` and `b` and all 642 /// equalities of both is created. 643 /// 644 /// An example of this case: 645 /// ___________ ___________ 646 /// / / | / / / 647 /// \ \ | / ==> \ / 648 /// \ \ | / \ / 649 /// \___\|/ \_____/ 650 /// 651 /// 652 LogicalResult SetCoalescer::coalescePairCutCase(unsigned i, unsigned j) { 653 /// All inequalities of `b` need to be redundant. We already know that the 654 /// redundant ones are, so only the cutting ones remain to be checked. 655 Simplex &simp = simplices[i]; 656 IntegerRelation &disjunct = disjuncts[i]; 657 if (llvm::any_of(cuttingIneqsA, [this, &simp](ArrayRef<int64_t> curr) { 658 return !isFacetContained(curr, simp); 659 })) 660 return failure(); 661 IntegerRelation newSet(disjunct.getSpace()); 662 663 for (ArrayRef<int64_t> curr : redundantIneqsA) 664 newSet.addInequality(curr); 665 666 for (ArrayRef<int64_t> curr : redundantIneqsB) 667 newSet.addInequality(curr); 668 669 addCoalescedDisjunct(i, j, newSet); 670 return success(); 671 } 672 673 LogicalResult SetCoalescer::typeInequality(ArrayRef<int64_t> ineq, 674 Simplex &simp) { 675 Simplex::IneqType type = simp.findIneqType(ineq); 676 if (type == Simplex::IneqType::Redundant) 677 redundantIneqsB.push_back(ineq); 678 else if (type == Simplex::IneqType::Cut) 679 cuttingIneqsB.push_back(ineq); 680 else 681 return failure(); 682 return success(); 683 } 684 685 LogicalResult SetCoalescer::typeEquality(ArrayRef<int64_t> eq, Simplex &simp) { 686 if (typeInequality(eq, simp).failed()) 687 return failure(); 688 negEqs.push_back(getNegatedCoeffs(eq)); 689 ArrayRef<int64_t> inv(negEqs.back()); 690 if (typeInequality(inv, simp).failed()) 691 return failure(); 692 return success(); 693 } 694 695 void SetCoalescer::eraseDisjunct(unsigned i) { 696 assert(simplices.size() == disjuncts.size() && 697 "simplices and disjuncts must be equally as long"); 698 disjuncts[i] = disjuncts.back(); 699 disjuncts.pop_back(); 700 simplices[i] = simplices.back(); 701 simplices.pop_back(); 702 } 703 704 LogicalResult SetCoalescer::coalescePair(unsigned i, unsigned j) { 705 706 IntegerRelation &a = disjuncts[i]; 707 IntegerRelation &b = disjuncts[j]; 708 /// Handling of local ids is not yet implemented, so these cases are 709 /// skipped. 710 /// TODO: implement local id support. 711 if (a.getNumLocalIds() != 0 || b.getNumLocalIds() != 0) 712 return failure(); 713 Simplex &simpA = simplices[i]; 714 Simplex &simpB = simplices[j]; 715 716 // Organize all inequalities and equalities of `a` according to their type 717 // for `b` into `redundantIneqsA` and `cuttingIneqsA` (and vice versa for 718 // all inequalities of `b` according to their type in `a`). If a separate 719 // inequality is encountered during typing, the two IntegerRelations 720 // cannot be coalesced. 721 for (int k = 0, e = a.getNumInequalities(); k < e; ++k) 722 if (typeInequality(a.getInequality(k), simpB).failed()) 723 return failure(); 724 725 for (int k = 0, e = a.getNumEqualities(); k < e; ++k) 726 if (typeEquality(a.getEquality(k), simpB).failed()) 727 return failure(); 728 729 std::swap(redundantIneqsA, redundantIneqsB); 730 std::swap(cuttingIneqsA, cuttingIneqsB); 731 732 for (int k = 0, e = b.getNumInequalities(); k < e; ++k) 733 if (typeInequality(b.getInequality(k), simpA).failed()) 734 return failure(); 735 736 for (int k = 0, e = b.getNumEqualities(); k < e; ++k) 737 if (typeEquality(b.getEquality(k), simpA).failed()) 738 return failure(); 739 740 // If there are no cutting inequalities of `a`, `b` is contained 741 // within `a`. 742 if (cuttingIneqsA.empty()) { 743 eraseDisjunct(j); 744 return success(); 745 } 746 747 // Try to apply the cut case 748 if (coalescePairCutCase(i, j).succeeded()) 749 return success(); 750 751 // Swap the vectors to compare the pair (j,i) instead of (i,j). 752 std::swap(redundantIneqsA, redundantIneqsB); 753 std::swap(cuttingIneqsA, cuttingIneqsB); 754 755 // If there are no cutting inequalities of `a`, `b` is contained 756 // within `a`. 757 if (cuttingIneqsA.empty()) { 758 eraseDisjunct(i); 759 return success(); 760 } 761 762 // Try to apply the cut case 763 if (coalescePairCutCase(j, i).succeeded()) 764 return success(); 765 766 return failure(); 767 } 768 769 PresburgerRelation PresburgerRelation::coalesce() const { 770 return SetCoalescer(*this).coalesce(); 771 } 772 773 void PresburgerRelation::print(raw_ostream &os) const { 774 os << "Number of Disjuncts: " << getNumDisjuncts() << "\n"; 775 for (const IntegerRelation &disjunct : disjuncts) { 776 disjunct.print(os); 777 os << '\n'; 778 } 779 } 780 781 void PresburgerRelation::dump() const { print(llvm::errs()); } 782 783 PresburgerSet PresburgerSet::getUniverse(const PresburgerSpace &space) { 784 PresburgerSet result(space); 785 result.unionInPlace(IntegerPolyhedron::getUniverse(space)); 786 return result; 787 } 788 789 PresburgerSet PresburgerSet::getEmpty(const PresburgerSpace &space) { 790 return PresburgerSet(space); 791 } 792 793 PresburgerSet::PresburgerSet(const IntegerPolyhedron &disjunct) 794 : PresburgerRelation(disjunct) {} 795 796 PresburgerSet::PresburgerSet(const PresburgerRelation &set) 797 : PresburgerRelation(set) {} 798 799 PresburgerSet PresburgerSet::unionSet(const PresburgerRelation &set) const { 800 return PresburgerSet(PresburgerRelation::unionSet(set)); 801 } 802 803 PresburgerSet PresburgerSet::intersect(const PresburgerRelation &set) const { 804 return PresburgerSet(PresburgerRelation::intersect(set)); 805 } 806 807 PresburgerSet PresburgerSet::complement() const { 808 return PresburgerSet(PresburgerRelation::complement()); 809 } 810 811 PresburgerSet PresburgerSet::subtract(const PresburgerRelation &set) const { 812 return PresburgerSet(PresburgerRelation::subtract(set)); 813 } 814 815 PresburgerSet PresburgerSet::coalesce() const { 816 return PresburgerSet(PresburgerRelation::coalesce()); 817 } 818