This is an archive of the discontinued LLVM Phabricator instance.

[llvm][ADT] Add a method to MapVector for erasing a range of elements.
AbandonedPublic

Authored by labrinea on Mar 16 2022, 8:58 AM.

Details

Summary

We currently support two ways to erase elements in MapVector: either erase a single element in linear time, which is rather expensive, or erase multiple elements based on a predicate. However, we may want to erase a range of contiguous elements. Here's a motivating example, where the current API is suboptimal:

MapVector.remove_if([&MapVector, N](const auto &Entry) {
  auto Iter = MapVector.find(Entry.first);
  return std::distance(Iter, MapVector.end()) > N;
});

Instead we could do:

N = MapVector.size() - N;
MapVector.erase(MapVector.begin(), MapVector.begin() + N);

Diff Detail

Event Timeline

labrinea created this revision.Mar 16 2022, 8:58 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 16 2022, 8:58 AM
labrinea requested review of this revision.Mar 16 2022, 8:58 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 16 2022, 8:58 AM

This reduces the total cost of the erase from O(N*M), where N is the total number of elements in the map and M is the number of elements you're removing, to O(N). That still seems like a significant performance hazard. I think we should discourage this sort of usage, in favor of a container where the removal is O(M), like std::map.

That said, depending on the usage, that might be okay, so I guess I'm not strongly against this.

llvm/include/llvm/ADT/MapVector.h
207

Asserting that you can't erase an empty range seems weird to me; standard library containers treat it as a no-op.

I agree with the complexity analysis here. I don't find a better solution if we don't add new data structures like a map from VectorType::iterator to MapType::iterator. It might benefit for erase but it is redundant for other methods. I think this patch is beneficial. And I feel it is good to comment that MapVector is not good at erase().

llvm/include/llvm/ADT/MapVector.h
49

This looks not necessary.

207

We could also assert begin() < S && S < E && E < end().

I didn't end up using this patch in https://reviews.llvm.org/D119880, but if you still find it useful I can address the review comments, otherwise I'll abandon it.

labrinea abandoned this revision.May 24 2023, 4:56 AM