[PATCH] Use Rvalue refs in APInt

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Tue May 31 23:25:18 PDT 2016


Hi Pete,

Thanks for brining this up, I think this is a relevant topic.  I've
specifically responded to this bit (I'll take a look at the patch
tomorrow):

> Yeah, i’ve been wondering about a BumpPtrAllocator, or even just a
> greater amount of inline storage.  An APInt is effectively a
> SmallVector<uint64_t, 1> in some sense but could have 2 or even more
> elements inline if it made sense.
>
> Given that the majority of long-lived APInt’s are uniqued inside
> ConstantInt, we may not even see much of a peak memory increase by
> doing this.  But its just a theory right now, and may be complicated
> to even try it.

My guess is that a lot of the malloc traffic, at least from SCEV,
comes from allocating 65 (== WordSize + 1) and 128 (== WordSize * 2)
bit APInts, and, as you said, the making APInts store two words inline
instead of one will solve these cases.

Btw, have you looked at the memory usage / malloc traffic due to
ConstantRanges?  If that too looks like it will be worth optimizing,
then we can try to kill two birds with one stone.  We can extract out
a CRTP-like thing containing the "big integer" algorithms and
(roughly) do:

// Use this in ConstantInt
template<unsigned N>
class APInt<N> : public APIntFunctions<APInt> {
  unsigned BitWidth;
  union {
    uint64_t Val[N];
    uint64_t *pVal;
  };

public:
  // Helpers to be used by APIntFunctions
};


This is quite a bit of extra work over just having a SmallVector<>
type design, but once we have this we can use this to optimize the
memory usage of ConstantRange.  ConstantRange has two APInts that have
to be of the same bitwidth, so once we have a separation between logic
and storage for APInts, we can make a ConstantRange be:

class ConstantRange {
  union {
    uint64_t LeftVal;
    uint64_t *pLeftVal;
  };
  union {
    uint64_t RightVal;
    uint64_t *pRightVal;
  };
  unsigned BitWidth;
};

and have a ConstantRange specific APInt implementation that
"dispatches" to the right storage as needed.



If ConstantRange does not look like it is worth optimizing, then a
straightforward

template<unsigned N>
class APInt<N> : APIntBaseImpl {
  unsigned BitWidth;
  union {
    uint64_t Val[N];
    uint64_t *pVal;
  };

public:
  // Implement public interface, using APIntBaseImpl to do the heavy lifting.
};


looks reasonable.

-- Sanjoy


More information about the llvm-commits mailing list