[llvm-commits] [PATCH] PR12156, SmallPtrMap

Chris Lattner clattner at apple.com
Sun Apr 1 09:32:42 PDT 2012


On Mar 30, 2012, at 12:34 AM, Stepan Dyatkovskiy wrote:

> Hi all. I reworked my patch again.
> In MultiImplMap class I added "bool DenseMapCompatible" template parameter that makes it DenseMap compatible. For DenseMapCompatible = true user should present map implementations with DenseMap specific methods, though.
> SmallMap became special case of MultiImplMap that uses FlatArrayMap for small mode, DenseMap for big mode and that set DenseMapCompatible = true.

Thank you for working on this Stepan!  This looks like great progress, though I have a strong concern about the design (stemming from the iterator, see the end).  Here are some random comments:


Please include a patch that updates the data structures section of docs/ProgrammerManual.html.


+//===- llvm/ADT/FlatArrayMap.h - 'Normally small' pointer set ----*- C++ -*-==//
...
+// After maximum number of elements is reached, map declines any farther attempts

"further attempts".  Also, please fit to 80 columns.



Please add a doxygen /// comment to the FlatArrayMap class definition.


Out of curiosity, why use:
+  template <typename KeyTy, typename MappedTy, unsigned N>
...
+    enum { ArraySize = N };

instead of just renaming 'N' to 'ArraySize'?

...
+    const_iterator begin() const {
+      return const_iterator(Array);    }

Please put } on the next line.


+    void clear() {
+      // Call destructor for each item and forget them.
+      for (unsigned i = 0; i < NumElements; ++i) {

This loop will reload NumElements every time through the loop if the dtors are non-trivial, please cache it in a local variable.

+//===- llvm/ADT/SmallMap.h - 'Normally small' pointer set ----*- C++ -*-===//

Please fill this out to exactly 80 columns.

+++ include/llvm/ADT/MultiImplMap.h	(revision 0)

+    void moveAllToBigMap() {
+        BigMap.insert(SmallMap.begin(), SmallMap.end());
+        SmallMap.clear();
+    }

This should just be inlined into its single caller.  If you really want it out of line, please indent by 2, not 4.


+    MultiImplMap(const self& other) {
+      UseSmall = other.UseSmall;
+      if (UseSmall)
+        SmallMap = other.SmallMap;
+      else
+        BigMap = other.BigMap;
+    }

Shouldn't this check the size of "other" and use SmallMap if it can?  If "other" started grew to "large" size, then had most of its elements removed (so that it could fit in "small") then was copied, it would make sense to start the copy out small.


+    void clear() {
+      if (UseSmall)
+        SmallMap.clear();
+      else
+        BigMap.clear();
+    }

In contrast to the copy ctor, this should stay the way it is.  Clearing a densemap doesn't free its buckets.  Please add a comment to this effect so that it is clearly intentional.


+    void swap(MultiImplMap& rhs) {
+}

Why not just define this as:

  SmallMap.swap(rhs.SmallMap);
  BigMap.swap(rhs.BitMap);

with no cases in it?


+    self& operator=(const self& other) {

Similar to the 'clear' method, switching back to small doesn't help you.  If 'this' is already big, stay big.



+  template<class SmallMapTy, class BigMapTy, bool IsConst>
+  class MultiImplMapIterator {

I'm not a big fan of this class: it is going to be really inefficient to copy around and deal with, particularly because so many of the MultiImplMap methods are defined in terms of it.  Can't we do something trickier if we drop the genericity of the underlying Array/Map classes?  A densemap is just an array of buckets, exactly like the small case.  If SmallMap took advantage of that, the iterator would be *much much* more efficient.

-Chris



More information about the llvm-commits mailing list