Skip to content

Commit 3ca5faa

Browse files
ericastorcopybara-github
authored andcommitted
Speed up IntervalSet::Complement.
The previous implementation modeled `Complement` as the intersection of the complements of the comprising intervals. However, since we already invoke `Intervals()` in this function, it only applies when the `IntervalSet` is already normalized... at which point, we can be more efficient by scanning linearly through the sorted list of non-abutting intervals & recording the unused values. PiperOrigin-RevId: 678405288
1 parent 145799a commit 3ca5faa

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

xls/ir/interval_set.cc

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -300,17 +300,28 @@ IntervalSet IntervalSet::Intersect(const IntervalSet& lhs,
300300
}
301301

302302
IntervalSet IntervalSet::Complement(const IntervalSet& set) {
303-
// The complement of an interval set is the intersection of the complements of
304-
// the component intervals.
305-
IntervalSet result = Maximal(set.BitCount());
303+
if (set.IsEmpty()) {
304+
return IntervalSet::Maximal(set.BitCount());
305+
}
306+
307+
IntervalSet result(set.BitCount());
308+
Bits last_taken = Bits::AllOnes(set.BitCount());
306309
for (const Interval& interval : set.Intervals()) {
307-
IntervalSet complement_set(set.BitCount());
308-
for (const Interval& complement : Interval::Complement(interval)) {
309-
complement_set.AddInterval(complement);
310+
// We rely on the fact that `set` is normalized if `Intervals()` was safe to
311+
// call, and that therefore:
312+
// 1. the intervals are sorted in increasing order by lower bound, and
313+
// 2. the intervals are not abutting or overlapping.
314+
Bits last_free = bits_ops::Decrement(interval.LowerBound());
315+
if (last_free != last_taken) {
316+
result.AddInterval(Interval::LeftOpen(last_taken, last_free));
310317
}
311-
complement_set.Normalize();
312-
result = Intersect(result, complement_set);
318+
last_taken = interval.UpperBound();
313319
}
320+
if (!last_taken.IsAllOnes()) {
321+
result.AddInterval(
322+
Interval::LeftOpen(last_taken, Bits::AllOnes(set.BitCount())));
323+
}
324+
result.Normalize();
314325
return result;
315326
}
316327

0 commit comments

Comments
 (0)