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