[llvm] Add ConstantRangeList::unionWith() and ::intersectWith() (PR #96547)
Arthur Eubanks via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 25 12:24:43 PDT 2024
================
@@ -81,6 +81,97 @@ void ConstantRangeList::insert(const ConstantRange &NewRange) {
}
}
+ConstantRangeList
+ConstantRangeList::unionWith(const ConstantRangeList &CRL) const {
+ assert(getBitWidth() == CRL.getBitWidth() &&
+ "ConstantRangeList bitwidths don't agree!");
+ // Handle common cases.
+ if (empty())
+ return CRL;
+ if (CRL.empty())
+ return *this;
+
+ ConstantRangeList Result;
+ size_t i = 0, j = 0;
+ // "PreviousRange" tracks the unioned range (its lower is fixed
+ // and the upper may be updated over iterations).
+ // If "PreviousRange" cannot contain a new unioned range, push it
+ // to the result and assign "PreviousRange" with the new range.
+ ConstantRange PreviousRange(getBitWidth(), false);
+ if (Ranges[i].getLower().slt(CRL.Ranges[j].getLower())) {
+ PreviousRange = Ranges[i++];
+ } else {
+ PreviousRange = CRL.Ranges[j++];
+ }
+
+ // Union "PreviousRange" and "CR". If they are disjoint, push "PreviousRange"
+ // to the result and assign it to "CR", a new union range. Otherwise, update
+ // the upper of "PreviousRange" to cover "CR". Note that, the lower of
+ // "PreviousRange" is always less or equal the lower of "CR".
+ auto UnionAndUpdateRange = [&PreviousRange,
+ &Result](const ConstantRange &CR) {
+ if (PreviousRange.getUpper().slt(CR.getLower())) {
+ Result.Ranges.push_back(PreviousRange);
+ PreviousRange = CR;
+ } else {
+ PreviousRange = ConstantRange(
+ PreviousRange.getLower(),
+ APIntOps::smax(PreviousRange.getUpper(), CR.getUpper()));
+ }
+ };
+ while (i < size() || j < CRL.size()) {
+ if (j == CRL.size() ||
+ (i < size() && Ranges[i].getLower().slt(CRL.Ranges[j].getLower()))) {
+ // Merge PreviousRange with this.
+ UnionAndUpdateRange(Ranges[i++]);
+ } else {
+ // Merge PreviousRange with CRL.
+ UnionAndUpdateRange(CRL.Ranges[j++]);
+ }
+ }
+ Result.Ranges.push_back(PreviousRange);
+ return Result;
+}
+
+ConstantRangeList
+ConstantRangeList::intersectWith(const ConstantRangeList &CRL) const {
+ assert(getBitWidth() == CRL.getBitWidth() &&
+ "ConstantRangeList bitwidths don't agree!");
+
+ // Handle common cases.
+ if (empty())
+ return *this;
+ if (CRL.empty())
+ return CRL;
+
+ ConstantRangeList Result;
+ size_t i = 0, j = 0;
+ while (i < size() && j < CRL.size()) {
+ auto &Range = this->Ranges[i];
+ auto &OtherRange = CRL.Ranges[j];
+
+ // The intersection of two Ranges is (max(lowers), min(uppers)), and it's
+ // possible that max(lowers) > min(uppers). Add the intersection to result
+ // only if it's a non-upper-wrapped range.
----------------
aeubanks wrote:
did you mean "empty" or did you actually mean "non-upper-wrapped"? I thought we didn't support upper-wrapped ranges at all?
https://github.com/llvm/llvm-project/pull/96547
More information about the llvm-commits
mailing list