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.containsPoint(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 simplex.detectRedundant(); 295 296 // Equalities are added to simplex as a pair of inequalities. 297 unsigned totalNewSimplexInequalities = 298 2 * sI.getNumEqualities() + sI.getNumInequalities(); 299 for (unsigned j = 0; j < totalNewSimplexInequalities; j++) 300 canIgnoreIneq[j] = simplex.isMarkedRedundant(offset + j); 301 simplex.rollback(snapshotBeforeIntersect); 302 303 SmallVector<unsigned, 8> ineqsToProcess(totalNewSimplexInequalities); 304 for (unsigned i = 0; i < totalNewSimplexInequalities; ++i) 305 if (!canIgnoreIneq[i]) 306 ineqsToProcess.push_back(i); 307 308 if (ineqsToProcess.empty()) { 309 // Nothing to process; return. (we have no frame to pop.) 310 level = frames.size(); 311 continue; 312 } 313 314 unsigned simplexSnapshot = simplex.getSnapshot(); 315 IntegerRelation::CountsSnapshot bCounts = b.getCounts(); 316 frames.push_back(Frame{simplexSnapshot, bCounts, sI, ineqsToProcess, 317 /*lastIneqProcessed=*/llvm::None}); 318 // We have completed the initial setup for this level. 319 // Fallthrough to the main recursive part below. 320 } 321 322 // For each inequality ineq, we first recurse with the part where ineq 323 // is not satisfied, and then add ineq to b and simplex because 324 // ineq must be satisfied by all later parts. 325 if (level == frames.size()) { 326 Frame &frame = frames.back(); 327 if (frame.lastIneqProcessed) { 328 // Let the current value of b be b' and 329 // let the initial value of b when we first came to this level be b. 330 // 331 // b' is equal to b /\ s_i1 /\ s_i2 /\ ... /\ s_i{j-1} /\ ~s_ij. 332 // We had previously recursed with the part where s_ij was not 333 // satisfied; all further parts satisfy s_ij, so we rollback to the 334 // state before adding this complement constraint, and add s_ij to b. 335 simplex.rollback(frame.simplexSnapshot); 336 b.truncate(frame.bCounts); 337 SmallVector<int64_t, 8> ineq = 338 getIneqCoeffsFromIdx(frame.sI, *frame.lastIneqProcessed); 339 b.addInequality(ineq); 340 simplex.addInequality(ineq); 341 } 342 343 if (frame.ineqsToProcess.empty()) { 344 // No ineqs left to process; pop this level's frame and return. 345 frames.pop_back(); 346 level = frames.size(); 347 continue; 348 } 349 350 // "Recurse" with the part where the ineq is not satisfied. 351 frame.bCounts = b.getCounts(); 352 frame.simplexSnapshot = simplex.getSnapshot(); 353 354 unsigned idx = frame.ineqsToProcess.back(); 355 SmallVector<int64_t, 8> ineq = 356 getComplementIneq(getIneqCoeffsFromIdx(frame.sI, idx)); 357 b.addInequality(ineq); 358 simplex.addInequality(ineq); 359 360 frame.ineqsToProcess.pop_back(); 361 frame.lastIneqProcessed = idx; 362 ++level; 363 continue; 364 } 365 } 366 367 return result; 368 } 369 370 /// Return the complement of this set. 371 PresburgerRelation PresburgerRelation::complement() const { 372 return getSetDifference(IntegerRelation::getUniverse(getSpace()), *this); 373 } 374 375 /// Return the result of subtract the given set from this set, i.e., 376 /// return `this \ set`. 377 PresburgerRelation 378 PresburgerRelation::subtract(const PresburgerRelation &set) const { 379 assert(space.isCompatible(set.getSpace()) && "Spaces should match"); 380 PresburgerRelation result(getSpace()); 381 // We compute (U_i t_i) \ (U_i set_i) as U_i (t_i \ V_i set_i). 382 for (const IntegerRelation &disjunct : disjuncts) 383 result.unionInPlace(getSetDifference(disjunct, set)); 384 return result; 385 } 386 387 /// T is a subset of S iff T \ S is empty, since if T \ S contains a 388 /// point then this is a point that is contained in T but not S, and 389 /// if T contains a point that is not in S, this also lies in T \ S. 390 bool PresburgerRelation::isSubsetOf(const PresburgerRelation &set) const { 391 return this->subtract(set).isIntegerEmpty(); 392 } 393 394 /// Two sets are equal iff they are subsets of each other. 395 bool PresburgerRelation::isEqual(const PresburgerRelation &set) const { 396 assert(space.isCompatible(set.getSpace()) && "Spaces should match"); 397 return this->isSubsetOf(set) && set.isSubsetOf(*this); 398 } 399 400 /// Return true if all the sets in the union are known to be integer empty, 401 /// false otherwise. 402 bool PresburgerRelation::isIntegerEmpty() const { 403 // The set is empty iff all of the disjuncts are empty. 404 return llvm::all_of(disjuncts, std::mem_fn(&IntegerRelation::isIntegerEmpty)); 405 } 406 407 bool PresburgerRelation::findIntegerSample(SmallVectorImpl<int64_t> &sample) { 408 // A sample exists iff any of the disjuncts contains a sample. 409 for (const IntegerRelation &disjunct : disjuncts) { 410 if (Optional<SmallVector<int64_t, 8>> opt = disjunct.findIntegerSample()) { 411 sample = std::move(*opt); 412 return true; 413 } 414 } 415 return false; 416 } 417 418 Optional<uint64_t> PresburgerRelation::computeVolume() const { 419 assert(getNumSymbolIds() == 0 && "Symbols are not yet supported!"); 420 // The sum of the volumes of the disjuncts is a valid overapproximation of the 421 // volume of their union, even if they overlap. 422 uint64_t result = 0; 423 for (const IntegerRelation &disjunct : disjuncts) { 424 Optional<uint64_t> volume = disjunct.computeVolume(); 425 if (!volume) 426 return {}; 427 result += *volume; 428 } 429 return result; 430 } 431 432 /// The SetCoalescer class contains all functionality concerning the coalesce 433 /// heuristic. It is built from a `PresburgerRelation` and has the `coalesce()` 434 /// function as its main API. The coalesce heuristic simplifies the 435 /// representation of a PresburgerRelation. In particular, it removes all 436 /// disjuncts which are subsets of other disjuncts in the union and it combines 437 /// sets that overlap and can be combined in a convex way. 438 class presburger::SetCoalescer { 439 440 public: 441 /// Simplifies the representation of a PresburgerSet. 442 PresburgerRelation coalesce(); 443 444 /// Construct a SetCoalescer from a PresburgerSet. 445 SetCoalescer(const PresburgerRelation &s); 446 447 private: 448 /// The space of the set the SetCoalescer is coalescing. 449 PresburgerSpace space; 450 451 /// The current list of `IntegerRelation`s that the currently coalesced set is 452 /// the union of. 453 SmallVector<IntegerRelation, 2> disjuncts; 454 /// The list of `Simplex`s constructed from the elements of `disjuncts`. 455 SmallVector<Simplex, 2> simplices; 456 457 /// The list of all inversed equalities during typing. This ensures that 458 /// the constraints exist even after the typing function has concluded. 459 SmallVector<SmallVector<int64_t, 2>, 2> negEqs; 460 461 /// `redundantIneqsA` is the inequalities of `a` that are redundant for `b` 462 /// (similarly for `cuttingIneqsA`, `redundantIneqsB`, and `cuttingIneqsB`). 463 SmallVector<ArrayRef<int64_t>, 2> redundantIneqsA; 464 SmallVector<ArrayRef<int64_t>, 2> cuttingIneqsA; 465 466 SmallVector<ArrayRef<int64_t>, 2> redundantIneqsB; 467 SmallVector<ArrayRef<int64_t>, 2> cuttingIneqsB; 468 469 /// Given a Simplex `simp` and one of its inequalities `ineq`, check 470 /// that the facet of `simp` where `ineq` holds as an equality is contained 471 /// within `a`. 472 bool isFacetContained(ArrayRef<int64_t> ineq, Simplex &simp); 473 474 /// Removes redundant constraints from `disjunct`, adds it to `disjuncts` and 475 /// removes the disjuncts at position `i` and `j`. Updates `simplices` to 476 /// reflect the changes. `i` and `j` cannot be equal. 477 void addCoalescedDisjunct(unsigned i, unsigned j, 478 const IntegerRelation &disjunct); 479 480 /// Checks whether `a` and `b` can be combined in a convex sense, if there 481 /// exist cutting inequalities. 482 /// 483 /// An example of this case: 484 /// ___________ ___________ 485 /// / / | / / / 486 /// \ \ | / ==> \ / 487 /// \ \ | / \ / 488 /// \___\|/ \_____/ 489 /// 490 /// 491 LogicalResult coalescePairCutCase(unsigned i, unsigned j); 492 493 /// Types the inequality `ineq` according to its `IneqType` for `simp` into 494 /// `redundantIneqsB` and `cuttingIneqsB`. Returns success, if no separate 495 /// inequalities were encountered. Otherwise, returns failure. 496 LogicalResult typeInequality(ArrayRef<int64_t> ineq, Simplex &simp); 497 498 /// Types the equality `eq`, i.e. for `eq` == 0, types both `eq` >= 0 and 499 /// -`eq` >= 0 according to their `IneqType` for `simp` into 500 /// `redundantIneqsB` and `cuttingIneqsB`. Returns success, if no separate 501 /// inequalities were encountered. Otherwise, returns failure. 502 LogicalResult typeEquality(ArrayRef<int64_t> eq, Simplex &simp); 503 504 /// Replaces the element at position `i` with the last element and erases 505 /// the last element for both `disjuncts` and `simplices`. 506 void eraseDisjunct(unsigned i); 507 508 /// Attempts to coalesce the two IntegerRelations at position `i` and `j` 509 /// in `disjuncts` in-place. Returns whether the disjuncts were 510 /// successfully coalesced. The simplices in `simplices` need to be the ones 511 /// constructed from `disjuncts`. At this point, there are no empty 512 /// disjuncts in `disjuncts` left. 513 LogicalResult coalescePair(unsigned i, unsigned j); 514 }; 515 516 /// Constructs a `SetCoalescer` from a `PresburgerRelation`. Only adds non-empty 517 /// `IntegerRelation`s to the `disjuncts` vector. 518 SetCoalescer::SetCoalescer(const PresburgerRelation &s) : space(s.getSpace()) { 519 520 disjuncts = s.disjuncts; 521 522 simplices.reserve(s.getNumDisjuncts()); 523 // Note that disjuncts.size() changes during the loop. 524 for (unsigned i = 0; i < disjuncts.size();) { 525 disjuncts[i].removeRedundantConstraints(); 526 Simplex simp(disjuncts[i]); 527 if (simp.isEmpty()) { 528 disjuncts[i] = disjuncts[disjuncts.size() - 1]; 529 disjuncts.pop_back(); 530 continue; 531 } 532 ++i; 533 simplices.push_back(simp); 534 } 535 } 536 537 /// Simplifies the representation of a PresburgerSet. 538 PresburgerRelation SetCoalescer::coalesce() { 539 // For all tuples of IntegerRelations, check whether they can be 540 // coalesced. When coalescing is successful, the contained IntegerRelation 541 // is swapped with the last element of `disjuncts` and subsequently erased 542 // and similarly for simplices. 543 for (unsigned i = 0; i < disjuncts.size();) { 544 545 // TODO: This does some comparisons two times (index 0 with 1 and index 1 546 // with 0). 547 bool broken = false; 548 for (unsigned j = 0, e = disjuncts.size(); j < e; ++j) { 549 negEqs.clear(); 550 redundantIneqsA.clear(); 551 redundantIneqsB.clear(); 552 cuttingIneqsA.clear(); 553 cuttingIneqsB.clear(); 554 if (i == j) 555 continue; 556 if (coalescePair(i, j).succeeded()) { 557 broken = true; 558 break; 559 } 560 } 561 562 // Only if the inner loop was not broken, i is incremented. This is 563 // required as otherwise, if a coalescing occurs, the IntegerRelation 564 // now at position i is not compared. 565 if (!broken) 566 ++i; 567 } 568 569 PresburgerRelation newSet = PresburgerRelation::getEmpty(space); 570 for (unsigned i = 0, e = disjuncts.size(); i < e; ++i) 571 newSet.unionInPlace(disjuncts[i]); 572 573 return newSet; 574 } 575 576 /// Given a Simplex `simp` and one of its inequalities `ineq`, check 577 /// that all inequalities of `cuttingIneqsB` are redundant for the facet of 578 /// `simp` where `ineq` holds as an equality is contained within `a`. 579 bool SetCoalescer::isFacetContained(ArrayRef<int64_t> ineq, Simplex &simp) { 580 SimplexRollbackScopeExit scopeExit(simp); 581 simp.addEquality(ineq); 582 return llvm::all_of(cuttingIneqsB, [&simp](ArrayRef<int64_t> curr) { 583 return simp.isRedundantInequality(curr); 584 }); 585 } 586 587 void SetCoalescer::addCoalescedDisjunct(unsigned i, unsigned j, 588 const IntegerRelation &disjunct) { 589 assert(i != j && "The indices must refer to different disjuncts"); 590 unsigned n = disjuncts.size(); 591 if (j == n - 1) { 592 // This case needs special handling since position `n` - 1 is removed 593 // from the vector, hence the `IntegerRelation` at position `n` - 2 is 594 // lost otherwise. 595 disjuncts[i] = disjuncts[n - 2]; 596 disjuncts.pop_back(); 597 disjuncts[n - 2] = disjunct; 598 disjuncts[n - 2].removeRedundantConstraints(); 599 600 simplices[i] = simplices[n - 2]; 601 simplices.pop_back(); 602 simplices[n - 2] = Simplex(disjuncts[n - 2]); 603 604 } else { 605 // Other possible edge cases are correct since for `j` or `i` == `n` - 606 // 2, the `IntegerRelation` at position `n` - 2 should be lost. The 607 // case `i` == `n` - 1 makes the first following statement a noop. 608 // Hence, in this case the same thing is done as above, but with `j` 609 // rather than `i`. 610 disjuncts[i] = disjuncts[n - 1]; 611 disjuncts[j] = disjuncts[n - 2]; 612 disjuncts.pop_back(); 613 disjuncts[n - 2] = disjunct; 614 disjuncts[n - 2].removeRedundantConstraints(); 615 616 simplices[i] = simplices[n - 1]; 617 simplices[j] = simplices[n - 2]; 618 simplices.pop_back(); 619 simplices[n - 2] = Simplex(disjuncts[n - 2]); 620 } 621 } 622 623 /// Given two polyhedra `a` and `b` at positions `i` and `j` in 624 /// `disjuncts` and `redundantIneqsA` being the inequalities of `a` that 625 /// are redundant for `b` (similarly for `cuttingIneqsA`, `redundantIneqsB`, 626 /// and `cuttingIneqsB`), Checks whether the facets of all cutting 627 /// inequalites of `a` are contained in `b`. If so, a new polyhedron 628 /// consisting of all redundant inequalites of `a` and `b` and all 629 /// equalities of both is created. 630 /// 631 /// An example of this case: 632 /// ___________ ___________ 633 /// / / | / / / 634 /// \ \ | / ==> \ / 635 /// \ \ | / \ / 636 /// \___\|/ \_____/ 637 /// 638 /// 639 LogicalResult SetCoalescer::coalescePairCutCase(unsigned i, unsigned j) { 640 /// All inequalities of `b` need to be redundant. We already know that the 641 /// redundant ones are, so only the cutting ones remain to be checked. 642 Simplex &simp = simplices[i]; 643 IntegerRelation &disjunct = disjuncts[i]; 644 if (llvm::any_of(cuttingIneqsA, [this, &simp](ArrayRef<int64_t> curr) { 645 return !isFacetContained(curr, simp); 646 })) 647 return failure(); 648 IntegerRelation newSet(disjunct.getSpace()); 649 650 for (ArrayRef<int64_t> curr : redundantIneqsA) 651 newSet.addInequality(curr); 652 653 for (ArrayRef<int64_t> curr : redundantIneqsB) 654 newSet.addInequality(curr); 655 656 addCoalescedDisjunct(i, j, newSet); 657 return success(); 658 } 659 660 LogicalResult SetCoalescer::typeInequality(ArrayRef<int64_t> ineq, 661 Simplex &simp) { 662 Simplex::IneqType type = simp.findIneqType(ineq); 663 if (type == Simplex::IneqType::Redundant) 664 redundantIneqsB.push_back(ineq); 665 else if (type == Simplex::IneqType::Cut) 666 cuttingIneqsB.push_back(ineq); 667 else 668 return failure(); 669 return success(); 670 } 671 672 LogicalResult SetCoalescer::typeEquality(ArrayRef<int64_t> eq, Simplex &simp) { 673 if (typeInequality(eq, simp).failed()) 674 return failure(); 675 negEqs.push_back(getNegatedCoeffs(eq)); 676 ArrayRef<int64_t> inv(negEqs.back()); 677 if (typeInequality(inv, simp).failed()) 678 return failure(); 679 return success(); 680 } 681 682 void SetCoalescer::eraseDisjunct(unsigned i) { 683 assert(simplices.size() == disjuncts.size() && 684 "simplices and disjuncts must be equally as long"); 685 disjuncts[i] = disjuncts.back(); 686 disjuncts.pop_back(); 687 simplices[i] = simplices.back(); 688 simplices.pop_back(); 689 } 690 691 LogicalResult SetCoalescer::coalescePair(unsigned i, unsigned j) { 692 693 IntegerRelation &a = disjuncts[i]; 694 IntegerRelation &b = disjuncts[j]; 695 /// Handling of local ids is not yet implemented, so these cases are 696 /// skipped. 697 /// TODO: implement local id support. 698 if (a.getNumLocalIds() != 0 || b.getNumLocalIds() != 0) 699 return failure(); 700 Simplex &simpA = simplices[i]; 701 Simplex &simpB = simplices[j]; 702 703 // Organize all inequalities and equalities of `a` according to their type 704 // for `b` into `redundantIneqsA` and `cuttingIneqsA` (and vice versa for 705 // all inequalities of `b` according to their type in `a`). If a separate 706 // inequality is encountered during typing, the two IntegerRelations 707 // cannot be coalesced. 708 for (int k = 0, e = a.getNumInequalities(); k < e; ++k) 709 if (typeInequality(a.getInequality(k), simpB).failed()) 710 return failure(); 711 712 for (int k = 0, e = a.getNumEqualities(); k < e; ++k) 713 if (typeEquality(a.getEquality(k), simpB).failed()) 714 return failure(); 715 716 std::swap(redundantIneqsA, redundantIneqsB); 717 std::swap(cuttingIneqsA, cuttingIneqsB); 718 719 for (int k = 0, e = b.getNumInequalities(); k < e; ++k) 720 if (typeInequality(b.getInequality(k), simpA).failed()) 721 return failure(); 722 723 for (int k = 0, e = b.getNumEqualities(); k < e; ++k) 724 if (typeEquality(b.getEquality(k), simpA).failed()) 725 return failure(); 726 727 // If there are no cutting inequalities of `a`, `b` is contained 728 // within `a`. 729 if (cuttingIneqsA.empty()) { 730 eraseDisjunct(j); 731 return success(); 732 } 733 734 // Try to apply the cut case 735 if (coalescePairCutCase(i, j).succeeded()) 736 return success(); 737 738 // Swap the vectors to compare the pair (j,i) instead of (i,j). 739 std::swap(redundantIneqsA, redundantIneqsB); 740 std::swap(cuttingIneqsA, cuttingIneqsB); 741 742 // If there are no cutting inequalities of `a`, `b` is contained 743 // within `a`. 744 if (cuttingIneqsA.empty()) { 745 eraseDisjunct(i); 746 return success(); 747 } 748 749 // Try to apply the cut case 750 if (coalescePairCutCase(j, i).succeeded()) 751 return success(); 752 753 return failure(); 754 } 755 756 PresburgerRelation PresburgerRelation::coalesce() const { 757 return SetCoalescer(*this).coalesce(); 758 } 759 760 void PresburgerRelation::print(raw_ostream &os) const { 761 os << "Number of Disjuncts: " << getNumDisjuncts() << "\n"; 762 for (const IntegerRelation &disjunct : disjuncts) { 763 disjunct.print(os); 764 os << '\n'; 765 } 766 } 767 768 void PresburgerRelation::dump() const { print(llvm::errs()); } 769 770 PresburgerSet PresburgerSet::getUniverse(const PresburgerSpace &space) { 771 PresburgerSet result(space); 772 result.unionInPlace(IntegerPolyhedron::getUniverse(space)); 773 return result; 774 } 775 776 PresburgerSet PresburgerSet::getEmpty(const PresburgerSpace &space) { 777 return PresburgerSet(space); 778 } 779 780 PresburgerSet::PresburgerSet(const IntegerPolyhedron &disjunct) 781 : PresburgerRelation(disjunct) {} 782 783 PresburgerSet::PresburgerSet(const PresburgerRelation &set) 784 : PresburgerRelation(set) {} 785 786 PresburgerSet PresburgerSet::unionSet(const PresburgerRelation &set) const { 787 return PresburgerSet(PresburgerRelation::unionSet(set)); 788 } 789 790 PresburgerSet PresburgerSet::intersect(const PresburgerRelation &set) const { 791 return PresburgerSet(PresburgerRelation::intersect(set)); 792 } 793 794 PresburgerSet PresburgerSet::complement() const { 795 return PresburgerSet(PresburgerRelation::complement()); 796 } 797 798 PresburgerSet PresburgerSet::subtract(const PresburgerRelation &set) const { 799 return PresburgerSet(PresburgerRelation::subtract(set)); 800 } 801 802 PresburgerSet PresburgerSet::coalesce() const { 803 return PresburgerSet(PresburgerRelation::coalesce()); 804 } 805