aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/ADT
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /include/llvm/ADT
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
downloadsrc-d8e91e46262bc44006913e6796843909f1ac7bcd.tar.gz
src-d8e91e46262bc44006913e6796843909f1ac7bcd.zip
Vendor import of llvm trunk r351319 (just before the release_80 branchvendor/llvm/llvm-trunk-r351319
Notes
Notes: svn path=/vendor/llvm/dist/; revision=343171 svn path=/vendor/llvm/llvm-trunk-r351319/; revision=343172; tag=vendor/llvm/llvm-trunk-r351319
Diffstat (limited to 'include/llvm/ADT')
-rw-r--r--include/llvm/ADT/APFloat.h36
-rw-r--r--include/llvm/ADT/APInt.h64
-rw-r--r--include/llvm/ADT/Any.h10
-rw-r--r--include/llvm/ADT/BitVector.h17
-rw-r--r--include/llvm/ADT/DenseMap.h81
-rw-r--r--include/llvm/ADT/DenseSet.h35
-rw-r--r--include/llvm/ADT/GraphTraits.h7
-rw-r--r--include/llvm/ADT/Hashing.h15
-rw-r--r--include/llvm/ADT/ImmutableList.h36
-rw-r--r--include/llvm/ADT/IntervalMap.h24
-rw-r--r--include/llvm/ADT/Optional.h22
-rw-r--r--include/llvm/ADT/PointerIntPair.h2
-rw-r--r--include/llvm/ADT/PointerSumType.h128
-rw-r--r--include/llvm/ADT/PostOrderIterator.h3
-rw-r--r--include/llvm/ADT/STLExtras.h358
-rw-r--r--include/llvm/ADT/SmallBitVector.h59
-rw-r--r--include/llvm/ADT/SmallVector.h10
-rw-r--r--include/llvm/ADT/SparseBitVector.h75
-rw-r--r--include/llvm/ADT/StringExtras.h11
-rw-r--r--include/llvm/ADT/Triple.h32
-rw-r--r--include/llvm/ADT/bit.h59
-rw-r--r--include/llvm/ADT/iterator.h38
22 files changed, 929 insertions, 193 deletions
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h
index 5c59af4c04ba..c6fa5ad674f6 100644
--- a/include/llvm/ADT/APFloat.h
+++ b/include/llvm/ADT/APFloat.h
@@ -870,13 +870,13 @@ public:
/// Factory for NaN values.
///
/// \param Negative - True iff the NaN generated should be negative.
- /// \param type - The unspecified fill bits for creating the NaN, 0 by
+ /// \param payload - The unspecified fill bits for creating the NaN, 0 by
/// default. The value is truncated as necessary.
static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
- unsigned type = 0) {
- if (type) {
- APInt fill(64, type);
- return getQNaN(Sem, Negative, &fill);
+ uint64_t payload = 0) {
+ if (payload) {
+ APInt intPayload(64, payload);
+ return getQNaN(Sem, Negative, &intPayload);
} else {
return getQNaN(Sem, Negative, nullptr);
}
@@ -1243,6 +1243,32 @@ inline APFloat maxnum(const APFloat &A, const APFloat &B) {
return (A.compare(B) == APFloat::cmpLessThan) ? B : A;
}
+/// Implements IEEE 754-2018 minimum semantics. Returns the smaller of 2
+/// arguments, propagating NaNs and treating -0 as less than +0.
+LLVM_READONLY
+inline APFloat minimum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return A;
+ if (B.isNaN())
+ return B;
+ if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
+ return A.isNegative() ? A : B;
+ return (B.compare(A) == APFloat::cmpLessThan) ? B : A;
+}
+
+/// Implements IEEE 754-2018 maximum semantics. Returns the larger of 2
+/// arguments, propagating NaNs and treating -0 as less than +0.
+LLVM_READONLY
+inline APFloat maximum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return A;
+ if (B.isNaN())
+ return B;
+ if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
+ return A.isNegative() ? B : A;
+ return (A.compare(B) == APFloat::cmpLessThan) ? B : A;
+}
+
} // namespace llvm
#undef APFLOAT_DISPATCH_ON_SEMANTICS
diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h
index 6bf6b22fb010..6e106ff8bf5d 100644
--- a/include/llvm/ADT/APInt.h
+++ b/include/llvm/ADT/APInt.h
@@ -31,6 +31,7 @@ class raw_ostream;
template <typename T> class SmallVectorImpl;
template <typename T> class ArrayRef;
+template <typename T> class Optional;
class APInt;
@@ -84,7 +85,7 @@ public:
UP,
};
- static const WordType WORD_MAX = ~WordType(0);
+ static const WordType WORDTYPE_MAX = ~WordType(0);
private:
/// This union is used to store the integer value. When the
@@ -149,7 +150,7 @@ private:
unsigned WordBits = ((BitWidth-1) % APINT_BITS_PER_WORD) + 1;
// Mask out the high bits.
- uint64_t mask = WORD_MAX >> (APINT_BITS_PER_WORD - WordBits);
+ uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - WordBits);
if (isSingleWord())
U.VAL &= mask;
else
@@ -394,7 +395,7 @@ public:
/// This checks to see if the value has all bits of the APInt are set or not.
bool isAllOnesValue() const {
if (isSingleWord())
- return U.VAL == WORD_MAX >> (APINT_BITS_PER_WORD - BitWidth);
+ return U.VAL == WORDTYPE_MAX >> (APINT_BITS_PER_WORD - BitWidth);
return countTrailingOnesSlowCase() == BitWidth;
}
@@ -495,7 +496,7 @@ public:
assert(numBits != 0 && "numBits must be non-zero");
assert(numBits <= BitWidth && "numBits out of range");
if (isSingleWord())
- return U.VAL == (WORD_MAX >> (APINT_BITS_PER_WORD - numBits));
+ return U.VAL == (WORDTYPE_MAX >> (APINT_BITS_PER_WORD - numBits));
unsigned Ones = countTrailingOnesSlowCase();
return (numBits == Ones) &&
((Ones + countLeadingZerosSlowCase()) == BitWidth);
@@ -559,7 +560,7 @@ public:
///
/// \returns the all-ones value for an APInt of the specified bit-width.
static APInt getAllOnesValue(unsigned numBits) {
- return APInt(numBits, WORD_MAX, true);
+ return APInt(numBits, WORDTYPE_MAX, true);
}
/// Get the '0' value.
@@ -1104,6 +1105,12 @@ public:
APInt sshl_ov(const APInt &Amt, bool &Overflow) const;
APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
+ // Operations that saturate
+ APInt sadd_sat(const APInt &RHS) const;
+ APInt uadd_sat(const APInt &RHS) const;
+ APInt ssub_sat(const APInt &RHS) const;
+ APInt usub_sat(const APInt &RHS) const;
+
/// Array-indexing support.
///
/// \returns the bit value at bitPosition
@@ -1382,7 +1389,7 @@ public:
/// Set every bit to 1.
void setAllBits() {
if (isSingleWord())
- U.VAL = WORD_MAX;
+ U.VAL = WORDTYPE_MAX;
else
// Set all the bits in all the words.
memset(U.pVal, -1, getNumWords() * APINT_WORD_SIZE);
@@ -1394,7 +1401,7 @@ public:
///
/// Set the given bit to 1 whose position is given as "bitPosition".
void setBit(unsigned BitPosition) {
- assert(BitPosition <= BitWidth && "BitPosition out of range");
+ assert(BitPosition < BitWidth && "BitPosition out of range");
WordType Mask = maskBit(BitPosition);
if (isSingleWord())
U.VAL |= Mask;
@@ -1415,7 +1422,7 @@ public:
if (loBit == hiBit)
return;
if (loBit < APINT_BITS_PER_WORD && hiBit <= APINT_BITS_PER_WORD) {
- uint64_t mask = WORD_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit));
+ uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit));
mask <<= loBit;
if (isSingleWord())
U.VAL |= mask;
@@ -1453,7 +1460,7 @@ public:
///
/// Set the given bit to 0 whose position is given as "bitPosition".
void clearBit(unsigned BitPosition) {
- assert(BitPosition <= BitWidth && "BitPosition out of range");
+ assert(BitPosition < BitWidth && "BitPosition out of range");
WordType Mask = ~maskBit(BitPosition);
if (isSingleWord())
U.VAL &= Mask;
@@ -1469,7 +1476,7 @@ public:
/// Toggle every bit to its opposite value.
void flipAllBits() {
if (isSingleWord()) {
- U.VAL ^= WORD_MAX;
+ U.VAL ^= WORDTYPE_MAX;
clearUnusedBits();
} else {
flipAllBitsSlowCase();
@@ -1758,7 +1765,7 @@ public:
/// referencing 2 in a space where 2 does no exist.
unsigned nearestLogBase2() const {
// Special case when we have a bitwidth of 1. If VAL is 1, then we
- // get 0. If VAL is 0, we get WORD_MAX which gets truncated to
+ // get 0. If VAL is 0, we get WORDTYPE_MAX which gets truncated to
// UINT32_MAX.
if (BitWidth == 1)
return U.VAL - 1;
@@ -2166,6 +2173,41 @@ APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM);
/// Return A sign-divided by B, rounded by the given rounding mode.
APInt RoundingSDiv(const APInt &A, const APInt &B, APInt::Rounding RM);
+/// Let q(n) = An^2 + Bn + C, and BW = bit width of the value range
+/// (e.g. 32 for i32).
+/// This function finds the smallest number n, such that
+/// (a) n >= 0 and q(n) = 0, or
+/// (b) n >= 1 and q(n-1) and q(n), when evaluated in the set of all
+/// integers, belong to two different intervals [Rk, Rk+R),
+/// where R = 2^BW, and k is an integer.
+/// The idea here is to find when q(n) "overflows" 2^BW, while at the
+/// same time "allowing" subtraction. In unsigned modulo arithmetic a
+/// subtraction (treated as addition of negated numbers) would always
+/// count as an overflow, but here we want to allow values to decrease
+/// and increase as long as they are within the same interval.
+/// Specifically, adding of two negative numbers should not cause an
+/// overflow (as long as the magnitude does not exceed the bith width).
+/// On the other hand, given a positive number, adding a negative
+/// number to it can give a negative result, which would cause the
+/// value to go from [-2^BW, 0) to [0, 2^BW). In that sense, zero is
+/// treated as a special case of an overflow.
+///
+/// This function returns None if after finding k that minimizes the
+/// positive solution to q(n) = kR, both solutions are contained between
+/// two consecutive integers.
+///
+/// There are cases where q(n) > T, and q(n+1) < T (assuming evaluation
+/// in arithmetic modulo 2^BW, and treating the values as signed) by the
+/// virtue of *signed* overflow. This function will *not* find such an n,
+/// however it may find a value of n satisfying the inequalities due to
+/// an *unsigned* overflow (if the values are treated as unsigned).
+/// To find a solution for a signed overflow, treat it as a problem of
+/// finding an unsigned overflow with a range with of BW-1.
+///
+/// The returned value may have a different bit width from the input
+/// coefficients.
+Optional<APInt> SolveQuadraticEquationWrap(APInt A, APInt B, APInt C,
+ unsigned RangeWidth);
} // End of APIntOps namespace
// See friend declaration above. This additional declaration is required in
diff --git a/include/llvm/ADT/Any.h b/include/llvm/ADT/Any.h
index c64c39987542..7faa4c963d3d 100644
--- a/include/llvm/ADT/Any.h
+++ b/include/llvm/ADT/Any.h
@@ -65,6 +65,16 @@ public:
typename std::enable_if<
llvm::conjunction<
llvm::negation<std::is_same<typename std::decay<T>::type, Any>>,
+ // We also disable this overload when an `Any` object can be
+ // converted to the parameter type because in that case, this
+ // constructor may combine with that conversion during overload
+ // resolution for determining copy constructibility, and then
+ // when we try to determine copy constructibility below we may
+ // infinitely recurse. This is being evaluated by the standards
+ // committee as a potential DR in `std::any` as well, but we're
+ // going ahead and adopting it to work-around usage of `Any` with
+ // types that need to be implicitly convertible from an `Any`.
+ llvm::negation<std::is_convertible<Any, typename std::decay<T>::type>>,
std::is_copy_constructible<typename std::decay<T>::type>>::value,
int>::type = 0>
Any(T &&Value) {
diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h
index 438c7d84c581..9ab1da7c6913 100644
--- a/include/llvm/ADT/BitVector.h
+++ b/include/llvm/ADT/BitVector.h
@@ -503,6 +503,23 @@ public:
return (*this)[Idx];
}
+ // Push single bit to end of vector.
+ void push_back(bool Val) {
+ unsigned OldSize = Size;
+ unsigned NewSize = Size + 1;
+
+ // Resize, which will insert zeros.
+ // If we already fit then the unused bits will be already zero.
+ if (NewSize > getBitCapacity())
+ resize(NewSize, false);
+ else
+ Size = NewSize;
+
+ // If true, set single bit.
+ if (Val)
+ set(OldSize);
+ }
+
/// Test if any common bits are set.
bool anyCommon(const BitVector &RHS) const {
unsigned ThisWords = NumBitWords(size());
diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h
index ba60b7972a8f..1f50502fff92 100644
--- a/include/llvm/ADT/DenseMap.h
+++ b/include/llvm/ADT/DenseMap.h
@@ -25,6 +25,7 @@
#include <cassert>
#include <cstddef>
#include <cstring>
+#include <initializer_list>
#include <iterator>
#include <new>
#include <type_traits>
@@ -38,6 +39,34 @@ namespace detail {
// implementation without requiring two members.
template <typename KeyT, typename ValueT>
struct DenseMapPair : public std::pair<KeyT, ValueT> {
+
+ // FIXME: Switch to inheriting constructors when we drop support for older
+ // clang versions.
+ // NOTE: This default constructor is declared with '{}' rather than
+ // '= default' to work around a separate bug in clang-3.8. This can
+ // also go when we switch to inheriting constructors.
+ DenseMapPair() {}
+
+ DenseMapPair(const KeyT &Key, const ValueT &Value)
+ : std::pair<KeyT, ValueT>(Key, Value) {}
+
+ DenseMapPair(KeyT &&Key, ValueT &&Value)
+ : std::pair<KeyT, ValueT>(std::move(Key), std::move(Value)) {}
+
+ template <typename AltKeyT, typename AltValueT>
+ DenseMapPair(AltKeyT &&AltKey, AltValueT &&AltValue,
+ typename std::enable_if<
+ std::is_convertible<AltKeyT, KeyT>::value &&
+ std::is_convertible<AltValueT, ValueT>::value>::type * = 0)
+ : std::pair<KeyT, ValueT>(std::forward<AltKeyT>(AltKey),
+ std::forward<AltValueT>(AltValue)) {}
+
+ template <typename AltPairT>
+ DenseMapPair(AltPairT &&AltPair,
+ typename std::enable_if<std::is_convertible<
+ AltPairT, std::pair<KeyT, ValueT>>::value>::type * = 0)
+ : std::pair<KeyT, ValueT>(std::forward<AltPairT>(AltPair)) {}
+
KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; }
const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; }
ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; }
@@ -46,9 +75,10 @@ struct DenseMapPair : public std::pair<KeyT, ValueT> {
} // end namespace detail
-template <
- typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>,
- typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false>
+template <typename KeyT, typename ValueT,
+ typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename Bucket = llvm::detail::DenseMapPair<KeyT, ValueT>,
+ bool IsConst = false>
class DenseMapIterator;
template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
@@ -393,7 +423,7 @@ protected:
setNumTombstones(other.getNumTombstones());
if (isPodLike<KeyT>::value && isPodLike<ValueT>::value)
- memcpy(getBuckets(), other.getBuckets(),
+ memcpy(reinterpret_cast<void *>(getBuckets()), other.getBuckets(),
getNumBuckets() * sizeof(BucketT));
else
for (size_t i = 0; i < getNumBuckets(); ++i) {
@@ -639,9 +669,43 @@ public:
}
};
+/// Equality comparison for DenseMap.
+///
+/// Iterates over elements of LHS confirming that each (key, value) pair in LHS
+/// is also in RHS, and that no additional pairs are in RHS.
+/// Equivalent to N calls to RHS.find and N value comparisons. Amortized
+/// complexity is linear, worst case is O(N^2) (if every hash collides).
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+ typename BucketT>
+bool operator==(
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
+ if (LHS.size() != RHS.size())
+ return false;
+
+ for (auto &KV : LHS) {
+ auto I = RHS.find(KV.first);
+ if (I == RHS.end() || I->second != KV.second)
+ return false;
+ }
+
+ return true;
+}
+
+/// Inequality comparison for DenseMap.
+///
+/// Equivalent to !(LHS == RHS). See operator== for performance notes.
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+ typename BucketT>
+bool operator!=(
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
+ return !(LHS == RHS);
+}
+
template <typename KeyT, typename ValueT,
typename KeyInfoT = DenseMapInfo<KeyT>,
- typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
+ typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>>
class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
KeyT, ValueT, KeyInfoT, BucketT> {
friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
@@ -676,6 +740,11 @@ public:
this->insert(I, E);
}
+ DenseMap(std::initializer_list<typename BaseT::value_type> Vals) {
+ init(Vals.size());
+ this->insert(Vals.begin(), Vals.end());
+ }
+
~DenseMap() {
this->destroyAll();
operator delete(Buckets);
@@ -798,7 +867,7 @@ private:
template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
typename KeyInfoT = DenseMapInfo<KeyT>,
- typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
+ typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>>
class SmallDenseMap
: public DenseMapBase<
SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h
index b495e25dd5e5..e85a38587e41 100644
--- a/include/llvm/ADT/DenseSet.h
+++ b/include/llvm/ADT/DenseSet.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/type_traits.h"
#include <algorithm>
#include <cstddef>
@@ -67,7 +68,7 @@ public:
explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {}
DenseSetImpl(std::initializer_list<ValueT> Elems)
- : DenseSetImpl(Elems.size()) {
+ : DenseSetImpl(PowerOf2Ceil(Elems.size())) {
insert(Elems.begin(), Elems.end());
}
@@ -136,8 +137,8 @@ public:
public:
using difference_type = typename MapTy::const_iterator::difference_type;
using value_type = ValueT;
- using pointer = value_type *;
- using reference = value_type &;
+ using pointer = const value_type *;
+ using reference = const value_type &;
using iterator_category = std::forward_iterator_tag;
ConstIterator() = default;
@@ -214,6 +215,34 @@ public:
}
};
+/// Equality comparison for DenseSet.
+///
+/// Iterates over elements of LHS confirming that each element is also a member
+/// of RHS, and that RHS contains no additional values.
+/// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst
+/// case is O(N^2) (if every hash collides).
+template <typename ValueT, typename MapTy, typename ValueInfoT>
+bool operator==(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
+ const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
+ if (LHS.size() != RHS.size())
+ return false;
+
+ for (auto &E : LHS)
+ if (!RHS.count(E))
+ return false;
+
+ return true;
+}
+
+/// Inequality comparison for DenseSet.
+///
+/// Equivalent to !(LHS == RHS). See operator== for performance notes.
+template <typename ValueT, typename MapTy, typename ValueInfoT>
+bool operator!=(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
+ const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
+ return !(LHS == RHS);
+}
+
} // end namespace detail
/// Implements a dense probed hash-table based set.
diff --git a/include/llvm/ADT/GraphTraits.h b/include/llvm/ADT/GraphTraits.h
index 27c647f4bbbd..d39b50fdc488 100644
--- a/include/llvm/ADT/GraphTraits.h
+++ b/include/llvm/ADT/GraphTraits.h
@@ -25,6 +25,13 @@ namespace llvm {
// GraphTraits - This class should be specialized by different graph types...
// which is why the default version is empty.
//
+// This template evolved from supporting `BasicBlock` to also later supporting
+// more complex types (e.g. CFG and DomTree).
+//
+// GraphTraits can be used to create a view over a graph interpreting it
+// differently without requiring a copy of the original graph. This could
+// be achieved by carrying more data in NodeRef. See LoopBodyTraits for one
+// example.
template<class GraphType>
struct GraphTraits {
// Elements to provide:
diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h
index 9f830baa4243..9175c545b7c9 100644
--- a/include/llvm/ADT/Hashing.h
+++ b/include/llvm/ADT/Hashing.h
@@ -133,7 +133,7 @@ hash_code hash_value(const std::basic_string<T> &arg);
/// undone. This makes it thread-hostile and very hard to use outside of
/// immediately on start of a simple program designed for reproducible
/// behavior.
-void set_fixed_execution_hash_seed(size_t fixed_value);
+void set_fixed_execution_hash_seed(uint64_t fixed_value);
// All of the implementation details of actually computing the various hash
@@ -316,9 +316,9 @@ struct hash_state {
/// This variable can be set using the \see llvm::set_fixed_execution_seed
/// function. See that function for details. Do not, under any circumstances,
/// set or read this variable.
-extern size_t fixed_seed_override;
+extern uint64_t fixed_seed_override;
-inline size_t get_execution_seed() {
+inline uint64_t get_execution_seed() {
// FIXME: This needs to be a per-execution seed. This is just a placeholder
// implementation. Switching to a per-execution seed is likely to flush out
// instability bugs and so will happen as its own commit.
@@ -326,8 +326,7 @@ inline size_t get_execution_seed() {
// However, if there is a fixed seed override set the first time this is
// called, return that instead of the per-execution seed.
const uint64_t seed_prime = 0xff51afd7ed558ccdULL;
- static size_t seed = fixed_seed_override ? fixed_seed_override
- : (size_t)seed_prime;
+ static uint64_t seed = fixed_seed_override ? fixed_seed_override : seed_prime;
return seed;
}
@@ -402,7 +401,7 @@ bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value,
/// combining them, this (as an optimization) directly combines the integers.
template <typename InputIteratorT>
hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
- const size_t seed = get_execution_seed();
+ const uint64_t seed = get_execution_seed();
char buffer[64], *buffer_ptr = buffer;
char *const buffer_end = std::end(buffer);
while (first != last && store_and_advance(buffer_ptr, buffer_end,
@@ -446,7 +445,7 @@ hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
template <typename ValueT>
typename std::enable_if<is_hashable_data<ValueT>::value, hash_code>::type
hash_combine_range_impl(ValueT *first, ValueT *last) {
- const size_t seed = get_execution_seed();
+ const uint64_t seed = get_execution_seed();
const char *s_begin = reinterpret_cast<const char *>(first);
const char *s_end = reinterpret_cast<const char *>(last);
const size_t length = std::distance(s_begin, s_end);
@@ -496,7 +495,7 @@ namespace detail {
struct hash_combine_recursive_helper {
char buffer[64];
hash_state state;
- const size_t seed;
+ const uint64_t seed;
public:
/// Construct a recursive hash combining helper.
diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h
index 1f5e9813798d..0541dc2566ed 100644
--- a/include/llvm/ADT/ImmutableList.h
+++ b/include/llvm/ADT/ImmutableList.h
@@ -31,8 +31,9 @@ class ImmutableListImpl : public FoldingSetNode {
T Head;
const ImmutableListImpl* Tail;
- ImmutableListImpl(const T& head, const ImmutableListImpl* tail = nullptr)
- : Head(head), Tail(tail) {}
+ template <typename ElemT>
+ ImmutableListImpl(ElemT &&head, const ImmutableListImpl *tail = nullptr)
+ : Head(std::forward<ElemT>(head)), Tail(tail) {}
public:
ImmutableListImpl(const ImmutableListImpl &) = delete;
@@ -66,6 +67,9 @@ public:
using value_type = T;
using Factory = ImmutableListFactory<T>;
+ static_assert(std::is_trivially_destructible<T>::value,
+ "T must be trivially destructible!");
+
private:
const ImmutableListImpl<T>* X;
@@ -90,6 +94,9 @@ public:
bool operator==(const iterator& I) const { return L == I.L; }
bool operator!=(const iterator& I) const { return L != I.L; }
const value_type& operator*() const { return L->getHead(); }
+ const typename std::remove_reference<value_type>::type* operator->() const {
+ return &L->getHead();
+ }
ImmutableList getList() const { return L; }
};
@@ -123,14 +130,14 @@ public:
bool operator==(const ImmutableList& L) const { return isEqual(L); }
/// getHead - Returns the head of the list.
- const T& getHead() {
+ const T& getHead() const {
assert(!isEmpty() && "Cannot get the head of an empty list.");
return X->getHead();
}
/// getTail - Returns the tail of the list, which is another (possibly empty)
/// ImmutableList.
- ImmutableList getTail() {
+ ImmutableList getTail() const {
return X ? X->getTail() : nullptr;
}
@@ -166,7 +173,8 @@ public:
if (ownsAllocator()) delete &getAllocator();
}
- LLVM_NODISCARD ImmutableList<T> concat(const T &Head, ImmutableList<T> Tail) {
+ template <typename ElemT>
+ LLVM_NODISCARD ImmutableList<T> concat(ElemT &&Head, ImmutableList<T> Tail) {
// Profile the new list to see if it already exists in our cache.
FoldingSetNodeID ID;
void* InsertPos;
@@ -179,7 +187,7 @@ public:
// The list does not exist in our cache. Create it.
BumpPtrAllocator& A = getAllocator();
L = (ListTy*) A.Allocate<ListTy>();
- new (L) ListTy(Head, TailImpl);
+ new (L) ListTy(std::forward<ElemT>(Head), TailImpl);
// Insert the new list into the cache.
Cache.InsertNode(L, InsertPos);
@@ -188,16 +196,24 @@ public:
return L;
}
- LLVM_NODISCARD ImmutableList<T> add(const T& D, ImmutableList<T> L) {
- return concat(D, L);
+ template <typename ElemT>
+ LLVM_NODISCARD ImmutableList<T> add(ElemT &&Data, ImmutableList<T> L) {
+ return concat(std::forward<ElemT>(Data), L);
+ }
+
+ template <typename ...CtorArgs>
+ LLVM_NODISCARD ImmutableList<T> emplace(ImmutableList<T> Tail,
+ CtorArgs &&...Args) {
+ return concat(T(std::forward<CtorArgs>(Args)...), Tail);
}
ImmutableList<T> getEmptyList() const {
return ImmutableList<T>(nullptr);
}
- ImmutableList<T> create(const T& X) {
- return Concat(X, getEmptyList());
+ template <typename ElemT>
+ ImmutableList<T> create(ElemT &&Data) {
+ return concat(std::forward<ElemT>(Data), getEmptyList());
}
};
diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h
index f71366811218..2af61049e5af 100644
--- a/include/llvm/ADT/IntervalMap.h
+++ b/include/llvm/ADT/IntervalMap.h
@@ -101,6 +101,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/bit.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/RecyclingAllocator.h"
@@ -963,6 +964,7 @@ public:
private:
// The root data is either a RootLeaf or a RootBranchData instance.
+ LLVM_ALIGNAS(RootLeaf) LLVM_ALIGNAS(RootBranchData)
AlignedCharArrayUnion<RootLeaf, RootBranchData> data;
// Tree height.
@@ -977,15 +979,10 @@ private:
// Allocator used for creating external nodes.
Allocator &allocator;
- /// dataAs - Represent data as a node type without breaking aliasing rules.
+ /// Represent data as a node type without breaking aliasing rules.
template <typename T>
T &dataAs() const {
- union {
- const char *d;
- T *t;
- } u;
- u.d = data.buffer;
- return *u.t;
+ return *bit_cast<T *>(const_cast<char *>(data.buffer));
}
const RootLeaf &rootLeaf() const {
@@ -1137,6 +1134,19 @@ public:
I.find(x);
return I;
}
+
+ /// overlaps(a, b) - Return true if the intervals in this map overlap with the
+ /// interval [a;b].
+ bool overlaps(KeyT a, KeyT b) {
+ assert(Traits::nonEmpty(a, b));
+ const_iterator I = find(a);
+ if (!I.valid())
+ return false;
+ // [a;b] and [x;y] overlap iff x<=b and a<=y. The find() call guarantees the
+ // second part (y = find(a).stop()), so it is sufficient to check the first
+ // one.
+ return !Traits::stopLess(b, I.start());
+ }
};
/// treeSafeLookup - Return the mapped value at x or NotFound, assuming a
diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h
index 353e5d0ec9df..76937d632ae1 100644
--- a/include/llvm/ADT/Optional.h
+++ b/include/llvm/ADT/Optional.h
@@ -29,7 +29,7 @@ namespace llvm {
namespace optional_detail {
/// Storage for any type.
-template <typename T, bool IsPodLike> struct OptionalStorage {
+template <typename T, bool = isPodLike<T>::value> struct OptionalStorage {
AlignedCharArrayUnion<T> storage;
bool hasVal = false;
@@ -108,28 +108,10 @@ template <typename T, bool IsPodLike> struct OptionalStorage {
}
};
-#if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this.
-/// Storage for trivially copyable types only.
-template <typename T> struct OptionalStorage<T, true> {
- AlignedCharArrayUnion<T> storage;
- bool hasVal = false;
-
- OptionalStorage() = default;
-
- OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
- OptionalStorage &operator=(const T &y) {
- *reinterpret_cast<T *>(storage.buffer) = y;
- hasVal = true;
- return *this;
- }
-
- void reset() { hasVal = false; }
-};
-#endif
} // namespace optional_detail
template <typename T> class Optional {
- optional_detail::OptionalStorage<T, isPodLike<T>::value> Storage;
+ optional_detail::OptionalStorage<T> Storage;
public:
using value_type = T;
diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h
index 884d05155bff..6d1b53a90ad2 100644
--- a/include/llvm/ADT/PointerIntPair.h
+++ b/include/llvm/ADT/PointerIntPair.h
@@ -42,6 +42,8 @@ template <typename PointerTy, unsigned IntBits, typename IntType = unsigned,
typename PtrTraits = PointerLikeTypeTraits<PointerTy>,
typename Info = PointerIntPairInfo<PointerTy, IntBits, PtrTraits>>
class PointerIntPair {
+ // Used by MSVC visualizer and generally helpful for debugging/visualizing.
+ using InfoTy = Info;
intptr_t Value = 0;
public:
diff --git a/include/llvm/ADT/PointerSumType.h b/include/llvm/ADT/PointerSumType.h
index e37957160d98..a19e45a46218 100644
--- a/include/llvm/ADT/PointerSumType.h
+++ b/include/llvm/ADT/PointerSumType.h
@@ -10,6 +10,7 @@
#ifndef LLVM_ADT_POINTERSUMTYPE_H
#define LLVM_ADT_POINTERSUMTYPE_H
+#include "llvm/ADT/bit.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
@@ -58,56 +59,142 @@ template <typename TagT, typename... MemberTs> struct PointerSumTypeHelper;
/// and may be desirable to set to a state that is particularly desirable to
/// default construct.
///
+/// Having a supported zero-valued tag also enables getting the address of a
+/// pointer stored with that tag provided it is stored in its natural bit
+/// representation. This works because in the case of a zero-valued tag, the
+/// pointer's value is directly stored into this object and we can expose the
+/// address of that internal storage. This is especially useful when building an
+/// `ArrayRef` of a single pointer stored in a sum type.
+///
/// There is no support for constructing or accessing with a dynamic tag as
/// that would fundamentally violate the type safety provided by the sum type.
template <typename TagT, typename... MemberTs> class PointerSumType {
- uintptr_t Value = 0;
-
using HelperT = detail::PointerSumTypeHelper<TagT, MemberTs...>;
+ // We keep both the raw value and the min tag value's pointer in a union. When
+ // the minimum tag value is zero, this allows code below to cleanly expose the
+ // address of the zero-tag pointer instead of just the zero-tag pointer
+ // itself. This is especially useful when building `ArrayRef`s out of a single
+ // pointer. However, we have to carefully access the union due to the active
+ // member potentially changing. When we *store* a new value, we directly
+ // access the union to allow us to store using the obvious types. However,
+ // when we *read* a value, we copy the underlying storage out to avoid relying
+ // on one member or the other being active.
+ union StorageT {
+ // Ensure we get a null default constructed value. We don't use a member
+ // initializer because some compilers seem to not implement those correctly
+ // for a union.
+ StorageT() : Value(0) {}
+
+ uintptr_t Value;
+
+ typename HelperT::template Lookup<HelperT::MinTag>::PointerT MinTagPointer;
+ };
+
+ StorageT Storage;
+
public:
constexpr PointerSumType() = default;
+ /// A typed setter to a given tagged member of the sum type.
+ template <TagT N>
+ void set(typename HelperT::template Lookup<N>::PointerT Pointer) {
+ void *V = HelperT::template Lookup<N>::TraitsT::getAsVoidPointer(Pointer);
+ assert((reinterpret_cast<uintptr_t>(V) & HelperT::TagMask) == 0 &&
+ "Pointer is insufficiently aligned to store the discriminant!");
+ Storage.Value = reinterpret_cast<uintptr_t>(V) | N;
+ }
+
/// A typed constructor for a specific tagged member of the sum type.
template <TagT N>
static PointerSumType
create(typename HelperT::template Lookup<N>::PointerT Pointer) {
PointerSumType Result;
- void *V = HelperT::template Lookup<N>::TraitsT::getAsVoidPointer(Pointer);
- assert((reinterpret_cast<uintptr_t>(V) & HelperT::TagMask) == 0 &&
- "Pointer is insufficiently aligned to store the discriminant!");
- Result.Value = reinterpret_cast<uintptr_t>(V) | N;
+ Result.set<N>(Pointer);
return Result;
}
- TagT getTag() const { return static_cast<TagT>(Value & HelperT::TagMask); }
+ /// Clear the value to null with the min tag type.
+ void clear() { set<HelperT::MinTag>(nullptr); }
+
+ TagT getTag() const {
+ return static_cast<TagT>(getOpaqueValue() & HelperT::TagMask);
+ }
template <TagT N> bool is() const { return N == getTag(); }
template <TagT N> typename HelperT::template Lookup<N>::PointerT get() const {
- void *P = is<N>() ? getImpl() : nullptr;
+ void *P = is<N>() ? getVoidPtr() : nullptr;
return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(P);
}
template <TagT N>
typename HelperT::template Lookup<N>::PointerT cast() const {
assert(is<N>() && "This instance has a different active member.");
- return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(getImpl());
+ return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(
+ getVoidPtr());
+ }
+
+ /// If the tag is zero and the pointer's value isn't changed when being
+ /// stored, get the address of the stored value type-punned to the zero-tag's
+ /// pointer type.
+ typename HelperT::template Lookup<HelperT::MinTag>::PointerT const *
+ getAddrOfZeroTagPointer() const {
+ return const_cast<PointerSumType *>(this)->getAddrOfZeroTagPointer();
}
- explicit operator bool() const { return Value & HelperT::PointerMask; }
- bool operator==(const PointerSumType &R) const { return Value == R.Value; }
- bool operator!=(const PointerSumType &R) const { return Value != R.Value; }
- bool operator<(const PointerSumType &R) const { return Value < R.Value; }
- bool operator>(const PointerSumType &R) const { return Value > R.Value; }
- bool operator<=(const PointerSumType &R) const { return Value <= R.Value; }
- bool operator>=(const PointerSumType &R) const { return Value >= R.Value; }
+ /// If the tag is zero and the pointer's value isn't changed when being
+ /// stored, get the address of the stored value type-punned to the zero-tag's
+ /// pointer type.
+ typename HelperT::template Lookup<HelperT::MinTag>::PointerT *
+ getAddrOfZeroTagPointer() {
+ static_assert(HelperT::MinTag == 0, "Non-zero minimum tag value!");
+ assert(is<HelperT::MinTag>() && "The active tag is not zero!");
+ // Store the initial value of the pointer when read out of our storage.
+ auto InitialPtr = get<HelperT::MinTag>();
+ // Now update the active member of the union to be the actual pointer-typed
+ // member so that accessing it indirectly through the returned address is
+ // valid.
+ Storage.MinTagPointer = InitialPtr;
+ // Finally, validate that this was a no-op as expected by reading it back
+ // out using the same underlying-storage read as above.
+ assert(InitialPtr == get<HelperT::MinTag>() &&
+ "Switching to typed storage changed the pointer returned!");
+ // Now we can correctly return an address to typed storage.
+ return &Storage.MinTagPointer;
+ }
+
+ explicit operator bool() const {
+ return getOpaqueValue() & HelperT::PointerMask;
+ }
+ bool operator==(const PointerSumType &R) const {
+ return getOpaqueValue() == R.getOpaqueValue();
+ }
+ bool operator!=(const PointerSumType &R) const {
+ return getOpaqueValue() != R.getOpaqueValue();
+ }
+ bool operator<(const PointerSumType &R) const {
+ return getOpaqueValue() < R.getOpaqueValue();
+ }
+ bool operator>(const PointerSumType &R) const {
+ return getOpaqueValue() > R.getOpaqueValue();
+ }
+ bool operator<=(const PointerSumType &R) const {
+ return getOpaqueValue() <= R.getOpaqueValue();
+ }
+ bool operator>=(const PointerSumType &R) const {
+ return getOpaqueValue() >= R.getOpaqueValue();
+ }
- uintptr_t getOpaqueValue() const { return Value; }
+ uintptr_t getOpaqueValue() const {
+ // Read the underlying storage of the union, regardless of the active
+ // member.
+ return bit_cast<uintptr_t>(Storage);
+ }
protected:
- void *getImpl() const {
- return reinterpret_cast<void *>(Value & HelperT::PointerMask);
+ void *getVoidPtr() const {
+ return reinterpret_cast<void *>(getOpaqueValue() & HelperT::PointerMask);
}
};
@@ -151,8 +238,9 @@ struct PointerSumTypeHelper : MemberTs... {
enum { NumTagBits = Min<MemberTs::TraitsT::NumLowBitsAvailable...>::value };
// Also compute the smallest discriminant and various masks for convenience.
+ constexpr static TagT MinTag =
+ static_cast<TagT>(Min<MemberTs::Tag...>::value);
enum : uint64_t {
- MinTag = Min<MemberTs::Tag...>::value,
PointerMask = static_cast<uint64_t>(-1) << NumTagBits,
TagMask = ~PointerMask
};
diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h
index dc8a9b6e78b2..d77b12228cb1 100644
--- a/include/llvm/ADT/PostOrderIterator.h
+++ b/include/llvm/ADT/PostOrderIterator.h
@@ -296,12 +296,15 @@ class ReversePostOrderTraversal {
public:
using rpo_iterator = typename std::vector<NodeRef>::reverse_iterator;
+ using const_rpo_iterator = typename std::vector<NodeRef>::const_reverse_iterator;
ReversePostOrderTraversal(GraphT G) { Initialize(GT::getEntryNode(G)); }
// Because we want a reverse post order, use reverse iterators from the vector
rpo_iterator begin() { return Blocks.rbegin(); }
+ const_rpo_iterator begin() const { return Blocks.crbegin(); }
rpo_iterator end() { return Blocks.rend(); }
+ const_rpo_iterator end() const { return Blocks.crend(); }
};
} // end namespace llvm
diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h
index 94365dd9ced1..f66ca7c08a73 100644
--- a/include/llvm/ADT/STLExtras.h
+++ b/include/llvm/ADT/STLExtras.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/Config/abi-breaking.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
@@ -70,6 +71,16 @@ template <typename B1, typename... Bn>
struct conjunction<B1, Bn...>
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
+template <typename T> struct make_const_ptr {
+ using type =
+ typename std::add_pointer<typename std::add_const<T>::type>::type;
+};
+
+template <typename T> struct make_const_ref {
+ using type = typename std::add_lvalue_reference<
+ typename std::add_const<T>::type>::type;
+};
+
//===----------------------------------------------------------------------===//
// Extra additions to <functional>
//===----------------------------------------------------------------------===//
@@ -194,6 +205,12 @@ void adl_swap(T &&lhs, T &&rhs) noexcept(
adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs));
}
+/// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty.
+template <typename T>
+constexpr bool empty(const T &RangeOrContainer) {
+ return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer);
+}
+
// mapped_iterator - This is a simple iterator adapter that causes a function to
// be applied whenever operator* is invoked on the iterator.
@@ -418,9 +435,94 @@ make_filter_range(RangeT &&Range, PredicateT Pred) {
std::end(std::forward<RangeT>(Range)), Pred));
}
-// forward declarations required by zip_shortest/zip_first
+/// A pseudo-iterator adaptor that is designed to implement "early increment"
+/// style loops.
+///
+/// This is *not a normal iterator* and should almost never be used directly. It
+/// is intended primarily to be used with range based for loops and some range
+/// algorithms.
+///
+/// The iterator isn't quite an `OutputIterator` or an `InputIterator` but
+/// somewhere between them. The constraints of these iterators are:
+///
+/// - On construction or after being incremented, it is comparable and
+/// dereferencable. It is *not* incrementable.
+/// - After being dereferenced, it is neither comparable nor dereferencable, it
+/// is only incrementable.
+///
+/// This means you can only dereference the iterator once, and you can only
+/// increment it once between dereferences.
+template <typename WrappedIteratorT>
+class early_inc_iterator_impl
+ : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
+ WrappedIteratorT, std::input_iterator_tag> {
+ using BaseT =
+ iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
+ WrappedIteratorT, std::input_iterator_tag>;
+
+ using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer;
+
+protected:
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ bool IsEarlyIncremented = false;
+#endif
+
+public:
+ early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {}
+
+ using BaseT::operator*;
+ typename BaseT::reference operator*() {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ assert(!IsEarlyIncremented && "Cannot dereference twice!");
+ IsEarlyIncremented = true;
+#endif
+ return *(this->I)++;
+ }
+
+ using BaseT::operator++;
+ early_inc_iterator_impl &operator++() {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ assert(IsEarlyIncremented && "Cannot increment before dereferencing!");
+ IsEarlyIncremented = false;
+#endif
+ return *this;
+ }
+
+ using BaseT::operator==;
+ bool operator==(const early_inc_iterator_impl &RHS) const {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ assert(!IsEarlyIncremented && "Cannot compare after dereferencing!");
+#endif
+ return BaseT::operator==(RHS);
+ }
+};
+
+/// Make a range that does early increment to allow mutation of the underlying
+/// range without disrupting iteration.
+///
+/// The underlying iterator will be incremented immediately after it is
+/// dereferenced, allowing deletion of the current node or insertion of nodes to
+/// not disrupt iteration provided they do not invalidate the *next* iterator --
+/// the current iterator can be invalidated.
+///
+/// This requires a very exact pattern of use that is only really suitable to
+/// range based for loops and other range algorithms that explicitly guarantee
+/// to dereference exactly once each element, and to increment exactly once each
+/// element.
+template <typename RangeT>
+iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>>
+make_early_inc_range(RangeT &&Range) {
+ using EarlyIncIteratorT =
+ early_inc_iterator_impl<detail::IterOfRange<RangeT>>;
+ return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))),
+ EarlyIncIteratorT(std::end(std::forward<RangeT>(Range))));
+}
+
+// forward declarations required by zip_shortest/zip_first/zip_longest
template <typename R, typename UnaryPredicate>
bool all_of(R &&range, UnaryPredicate P);
+template <typename R, typename UnaryPredicate>
+bool any_of(R &&range, UnaryPredicate P);
template <size_t... I> struct index_sequence;
@@ -571,6 +673,132 @@ detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u,
std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
}
+namespace detail {
+template <typename Iter>
+static Iter next_or_end(const Iter &I, const Iter &End) {
+ if (I == End)
+ return End;
+ return std::next(I);
+}
+
+template <typename Iter>
+static auto deref_or_none(const Iter &I, const Iter &End)
+ -> llvm::Optional<typename std::remove_const<
+ typename std::remove_reference<decltype(*I)>::type>::type> {
+ if (I == End)
+ return None;
+ return *I;
+}
+
+template <typename Iter> struct ZipLongestItemType {
+ using type =
+ llvm::Optional<typename std::remove_const<typename std::remove_reference<
+ decltype(*std::declval<Iter>())>::type>::type>;
+};
+
+template <typename... Iters> struct ZipLongestTupleType {
+ using type = std::tuple<typename ZipLongestItemType<Iters>::type...>;
+};
+
+template <typename... Iters>
+class zip_longest_iterator
+ : public iterator_facade_base<
+ zip_longest_iterator<Iters...>,
+ typename std::common_type<
+ std::forward_iterator_tag,
+ typename std::iterator_traits<Iters>::iterator_category...>::type,
+ typename ZipLongestTupleType<Iters...>::type,
+ typename std::iterator_traits<typename std::tuple_element<
+ 0, std::tuple<Iters...>>::type>::difference_type,
+ typename ZipLongestTupleType<Iters...>::type *,
+ typename ZipLongestTupleType<Iters...>::type> {
+public:
+ using value_type = typename ZipLongestTupleType<Iters...>::type;
+
+private:
+ std::tuple<Iters...> iterators;
+ std::tuple<Iters...> end_iterators;
+
+ template <size_t... Ns>
+ bool test(const zip_longest_iterator<Iters...> &other,
+ index_sequence<Ns...>) const {
+ return llvm::any_of(
+ std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
+ std::get<Ns>(other.iterators)...},
+ identity<bool>{});
+ }
+
+ template <size_t... Ns> value_type deref(index_sequence<Ns...>) const {
+ return value_type(
+ deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
+ }
+
+ template <size_t... Ns>
+ decltype(iterators) tup_inc(index_sequence<Ns...>) const {
+ return std::tuple<Iters...>(
+ next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
+ }
+
+public:
+ zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts)
+ : iterators(std::forward<Iters>(ts.first)...),
+ end_iterators(std::forward<Iters>(ts.second)...) {}
+
+ value_type operator*() { return deref(index_sequence_for<Iters...>{}); }
+
+ value_type operator*() const { return deref(index_sequence_for<Iters...>{}); }
+
+ zip_longest_iterator<Iters...> &operator++() {
+ iterators = tup_inc(index_sequence_for<Iters...>{});
+ return *this;
+ }
+
+ bool operator==(const zip_longest_iterator<Iters...> &other) const {
+ return !test(other, index_sequence_for<Iters...>{});
+ }
+};
+
+template <typename... Args> class zip_longest_range {
+public:
+ using iterator =
+ zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>;
+ using iterator_category = typename iterator::iterator_category;
+ using value_type = typename iterator::value_type;
+ using difference_type = typename iterator::difference_type;
+ using pointer = typename iterator::pointer;
+ using reference = typename iterator::reference;
+
+private:
+ std::tuple<Args...> ts;
+
+ template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const {
+ return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)),
+ adl_end(std::get<Ns>(ts)))...);
+ }
+
+ template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const {
+ return iterator(std::make_pair(adl_end(std::get<Ns>(ts)),
+ adl_end(std::get<Ns>(ts)))...);
+ }
+
+public:
+ zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
+
+ iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); }
+ iterator end() const { return end_impl(index_sequence_for<Args...>{}); }
+};
+} // namespace detail
+
+/// Iterate over two or more iterators at the same time. Iteration continues
+/// until all iterators reach the end. The llvm::Optional only contains a value
+/// if the iterator has not reached the end.
+template <typename T, typename U, typename... Args>
+detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u,
+ Args &&... args) {
+ return detail::zip_longest_range<T, U, Args...>(
+ std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
+}
+
/// Iterator wrapper that concatenates sequences together.
///
/// This can concatenate different iterators, even with different types, into
@@ -593,18 +821,20 @@ class concat_iterator
/// Note that something like iterator_range seems nice at first here, but the
/// range properties are of little benefit and end up getting in the way
/// because we need to do mutation on the current iterators.
- std::tuple<std::pair<IterTs, IterTs>...> IterPairs;
+ std::tuple<IterTs...> Begins;
+ std::tuple<IterTs...> Ends;
/// Attempts to increment a specific iterator.
///
/// Returns true if it was able to increment the iterator. Returns false if
/// the iterator is already at the end iterator.
template <size_t Index> bool incrementHelper() {
- auto &IterPair = std::get<Index>(IterPairs);
- if (IterPair.first == IterPair.second)
+ auto &Begin = std::get<Index>(Begins);
+ auto &End = std::get<Index>(Ends);
+ if (Begin == End)
return false;
- ++IterPair.first;
+ ++Begin;
return true;
}
@@ -628,11 +858,12 @@ class concat_iterator
/// dereferences the iterator and returns the address of the resulting
/// reference.
template <size_t Index> ValueT *getHelper() const {
- auto &IterPair = std::get<Index>(IterPairs);
- if (IterPair.first == IterPair.second)
+ auto &Begin = std::get<Index>(Begins);
+ auto &End = std::get<Index>(Ends);
+ if (Begin == End)
return nullptr;
- return &*IterPair.first;
+ return &*Begin;
}
/// Finds the first non-end iterator, dereferences, and returns the resulting
@@ -659,7 +890,7 @@ public:
/// iterators.
template <typename... RangeTs>
explicit concat_iterator(RangeTs &&... Ranges)
- : IterPairs({std::begin(Ranges), std::end(Ranges)}...) {}
+ : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {}
using BaseT::operator++;
@@ -671,7 +902,7 @@ public:
ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); }
bool operator==(const concat_iterator &RHS) const {
- return IterPairs == RHS.IterPairs;
+ return Begins == RHS.Begins && Ends == RHS.Ends;
}
};
@@ -740,6 +971,19 @@ struct less_second {
}
};
+/// \brief Function object to apply a binary function to the first component of
+/// a std::pair.
+template<typename FuncTy>
+struct on_first {
+ FuncTy func;
+
+ template <typename T>
+ auto operator()(const T &lhs, const T &rhs) const
+ -> decltype(func(lhs.first, rhs.first)) {
+ return func(lhs.first, rhs.first);
+ }
+};
+
// A subset of N3658. More stuff can be added as-needed.
/// Represents a compile-time sequence of integers.
@@ -877,6 +1121,10 @@ inline void sort(IteratorTy Start, IteratorTy End) {
std::sort(Start, End);
}
+template <typename Container> inline void sort(Container &&C) {
+ llvm::sort(adl_begin(C), adl_end(C));
+}
+
template <typename IteratorTy, typename Compare>
inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
#ifdef EXPENSIVE_CHECKS
@@ -886,6 +1134,11 @@ inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
std::sort(Start, End, Comp);
}
+template <typename Container, typename Compare>
+inline void sort(Container &&C, Compare Comp) {
+ llvm::sort(adl_begin(C), adl_end(C), Comp);
+}
+
//===----------------------------------------------------------------------===//
// Extra additions to <algorithm>
//===----------------------------------------------------------------------===//
@@ -908,6 +1161,18 @@ void DeleteContainerSeconds(Container &C) {
C.clear();
}
+/// Get the size of a range. This is a wrapper function around std::distance
+/// which is only enabled when the operation is O(1).
+template <typename R>
+auto size(R &&Range, typename std::enable_if<
+ std::is_same<typename std::iterator_traits<decltype(
+ Range.begin())>::iterator_category,
+ std::random_access_iterator_tag>::value,
+ void>::type * = nullptr)
+ -> decltype(std::distance(Range.begin(), Range.end())) {
+ return std::distance(Range.begin(), Range.end());
+}
+
/// Provide wrappers to std::for_each which take ranges instead of having to
/// pass begin/end explicitly.
template <typename R, typename UnaryPredicate>
@@ -1018,6 +1283,33 @@ auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) {
return std::lower_bound(adl_begin(Range), adl_end(Range), I);
}
+template <typename R, typename ForwardIt, typename Compare>
+auto lower_bound(R &&Range, ForwardIt I, Compare C)
+ -> decltype(adl_begin(Range)) {
+ return std::lower_bound(adl_begin(Range), adl_end(Range), I, C);
+}
+
+/// Provide wrappers to std::upper_bound which take ranges instead of having to
+/// pass begin/end explicitly.
+template <typename R, typename ForwardIt>
+auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) {
+ return std::upper_bound(adl_begin(Range), adl_end(Range), I);
+}
+
+template <typename R, typename ForwardIt, typename Compare>
+auto upper_bound(R &&Range, ForwardIt I, Compare C)
+ -> decltype(adl_begin(Range)) {
+ return std::upper_bound(adl_begin(Range), adl_end(Range), I, C);
+}
+/// Wrapper function around std::equal to detect if all elements
+/// in a container are same.
+template <typename R>
+bool is_splat(R &&Range) {
+ size_t range_size = size(Range);
+ return range_size != 0 && (range_size == 1 ||
+ std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range)));
+}
+
/// Given a range of type R, iterate the entire range and return a
/// SmallVector with elements of the vector. This is useful, for example,
/// when you want to iterate a range and then sort the results.
@@ -1039,18 +1331,6 @@ void erase_if(Container &C, UnaryPredicate P) {
C.erase(remove_if(C, P), C.end());
}
-/// Get the size of a range. This is a wrapper function around std::distance
-/// which is only enabled when the operation is O(1).
-template <typename R>
-auto size(R &&Range, typename std::enable_if<
- std::is_same<typename std::iterator_traits<decltype(
- Range.begin())>::iterator_category,
- std::random_access_iterator_tag>::value,
- void>::type * = nullptr)
- -> decltype(std::distance(Range.begin(), Range.end())) {
- return std::distance(Range.begin(), Range.end());
-}
-
//===----------------------------------------------------------------------===//
// Extra additions to <memory>
//===----------------------------------------------------------------------===//
@@ -1263,6 +1543,40 @@ auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl(
Indices{});
}
+/// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N)
+/// time. Not meant for use with random-access iterators.
+template <typename IterTy>
+bool hasNItems(
+ IterTy &&Begin, IterTy &&End, unsigned N,
+ typename std::enable_if<
+ !std::is_same<
+ typename std::iterator_traits<typename std::remove_reference<
+ decltype(Begin)>::type>::iterator_category,
+ std::random_access_iterator_tag>::value,
+ void>::type * = nullptr) {
+ for (; N; --N, ++Begin)
+ if (Begin == End)
+ return false; // Too few.
+ return Begin == End;
+}
+
+/// Return true if the sequence [Begin, End) has N or more items. Runs in O(N)
+/// time. Not meant for use with random-access iterators.
+template <typename IterTy>
+bool hasNItemsOrMore(
+ IterTy &&Begin, IterTy &&End, unsigned N,
+ typename std::enable_if<
+ !std::is_same<
+ typename std::iterator_traits<typename std::remove_reference<
+ decltype(Begin)>::type>::iterator_category,
+ std::random_access_iterator_tag>::value,
+ void>::type * = nullptr) {
+ for (; N; --N, ++Begin)
+ if (Begin == End)
+ return false; // Too few.
+ return true;
+}
+
} // end namespace llvm
#endif // LLVM_ADT_STLEXTRAS_H
diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h
index b6391746639b..0a73dbd60671 100644
--- a/include/llvm/ADT/SmallBitVector.h
+++ b/include/llvm/ADT/SmallBitVector.h
@@ -92,10 +92,6 @@ public:
};
private:
- bool isSmall() const {
- return X & uintptr_t(1);
- }
-
BitVector *getPointer() const {
assert(!isSmall());
return reinterpret_cast<BitVector *>(X);
@@ -186,6 +182,8 @@ public:
return make_range(set_bits_begin(), set_bits_end());
}
+ bool isSmall() const { return X & uintptr_t(1); }
+
/// Tests whether there are no bits in this bitvector.
bool empty() const {
return isSmall() ? getSmallSize() == 0 : getPointer()->empty();
@@ -242,7 +240,7 @@ public:
uintptr_t Bits = getSmallBits();
if (Bits == 0)
return -1;
- return NumBaseBits - countLeadingZeros(Bits);
+ return NumBaseBits - countLeadingZeros(Bits) - 1;
}
return getPointer()->find_last();
}
@@ -265,7 +263,9 @@ public:
return -1;
uintptr_t Bits = getSmallBits();
- return NumBaseBits - countLeadingOnes(Bits);
+ // Set unused bits.
+ Bits |= ~uintptr_t(0) << getSmallSize();
+ return NumBaseBits - countLeadingOnes(Bits) - 1;
}
return getPointer()->find_last_unset();
}
@@ -465,6 +465,11 @@ public:
return (*this)[Idx];
}
+ // Push single bit to end of vector.
+ void push_back(bool Val) {
+ resize(size() + 1, Val);
+ }
+
/// Test if any common bits are set.
bool anyCommon(const SmallBitVector &RHS) const {
if (isSmall() && RHS.isSmall())
@@ -482,10 +487,17 @@ public:
bool operator==(const SmallBitVector &RHS) const {
if (size() != RHS.size())
return false;
- if (isSmall())
+ if (isSmall() && RHS.isSmall())
return getSmallBits() == RHS.getSmallBits();
- else
+ else if (!isSmall() && !RHS.isSmall())
return *getPointer() == *RHS.getPointer();
+ else {
+ for (size_t i = 0, e = size(); i != e; ++i) {
+ if ((*this)[i] != RHS[i])
+ return false;
+ }
+ return true;
+ }
}
bool operator!=(const SmallBitVector &RHS) const {
@@ -493,16 +505,19 @@ public:
}
// Intersection, union, disjoint union.
+ // FIXME BitVector::operator&= does not resize the LHS but this does
SmallBitVector &operator&=(const SmallBitVector &RHS) {
resize(std::max(size(), RHS.size()));
- if (isSmall())
+ if (isSmall() && RHS.isSmall())
setSmallBits(getSmallBits() & RHS.getSmallBits());
- else if (!RHS.isSmall())
+ else if (!isSmall() && !RHS.isSmall())
getPointer()->operator&=(*RHS.getPointer());
else {
- SmallBitVector Copy = RHS;
- Copy.resize(size());
- getPointer()->operator&=(*Copy.getPointer());
+ size_t i, e;
+ for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i)
+ (*this)[i] = test(i) && RHS.test(i);
+ for (e = size(); i != e; ++i)
+ reset(i);
}
return *this;
}
@@ -542,28 +557,26 @@ public:
SmallBitVector &operator|=(const SmallBitVector &RHS) {
resize(std::max(size(), RHS.size()));
- if (isSmall())
+ if (isSmall() && RHS.isSmall())
setSmallBits(getSmallBits() | RHS.getSmallBits());
- else if (!RHS.isSmall())
+ else if (!isSmall() && !RHS.isSmall())
getPointer()->operator|=(*RHS.getPointer());
else {
- SmallBitVector Copy = RHS;
- Copy.resize(size());
- getPointer()->operator|=(*Copy.getPointer());
+ for (size_t i = 0, e = RHS.size(); i != e; ++i)
+ (*this)[i] = test(i) || RHS.test(i);
}
return *this;
}
SmallBitVector &operator^=(const SmallBitVector &RHS) {
resize(std::max(size(), RHS.size()));
- if (isSmall())
+ if (isSmall() && RHS.isSmall())
setSmallBits(getSmallBits() ^ RHS.getSmallBits());
- else if (!RHS.isSmall())
+ else if (!isSmall() && !RHS.isSmall())
getPointer()->operator^=(*RHS.getPointer());
else {
- SmallBitVector Copy = RHS;
- Copy.resize(size());
- getPointer()->operator^=(*Copy.getPointer());
+ for (size_t i = 0, e = RHS.size(); i != e; ++i)
+ (*this)[i] = test(i) != RHS.test(i);
}
return *this;
}
diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h
index acb4426b4f45..0636abbb1fbf 100644
--- a/include/llvm/ADT/SmallVector.h
+++ b/include/llvm/ADT/SmallVector.h
@@ -182,7 +182,7 @@ public:
/// SmallVectorTemplateBase<isPodLike = false> - This is where we put method
/// implementations that are designed to work with non-POD-like T's.
-template <typename T, bool isPodLike>
+template <typename T, bool = isPodLike<T>::value>
class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
protected:
SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
@@ -299,7 +299,7 @@ protected:
// use memcpy here. Note that I and E are iterators and thus might be
// invalid for memcpy if they are equal.
if (I != E)
- memcpy(Dest, I, (E - I) * sizeof(T));
+ memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T));
}
/// Double the size of the allocated memory, guaranteeing space for at
@@ -310,7 +310,7 @@ public:
void push_back(const T &Elt) {
if (LLVM_UNLIKELY(this->size() >= this->capacity()))
this->grow();
- memcpy(this->end(), &Elt, sizeof(T));
+ memcpy(reinterpret_cast<void *>(this->end()), &Elt, sizeof(T));
this->set_size(this->size() + 1);
}
@@ -320,8 +320,8 @@ public:
/// This class consists of common code factored out of the SmallVector class to
/// reduce code duplication based on the SmallVector 'N' template parameter.
template <typename T>
-class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
- using SuperClass = SmallVectorTemplateBase<T, isPodLike<T>::value>;
+class SmallVectorImpl : public SmallVectorTemplateBase<T> {
+ using SuperClass = SmallVectorTemplateBase<T>;
public:
using iterator = typename SuperClass::iterator;
diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h
index 4cbf40c76805..84e73bcbace8 100644
--- a/include/llvm/ADT/SparseBitVector.h
+++ b/include/llvm/ADT/SparseBitVector.h
@@ -261,21 +261,33 @@ class SparseBitVector {
BITWORD_SIZE = SparseBitVectorElement<ElementSize>::BITWORD_SIZE
};
- // Pointer to our current Element.
- ElementListIter CurrElementIter;
ElementList Elements;
+ // Pointer to our current Element. This has no visible effect on the external
+ // state of a SparseBitVector, it's just used to improve performance in the
+ // common case of testing/modifying bits with similar indices.
+ mutable ElementListIter CurrElementIter;
// This is like std::lower_bound, except we do linear searching from the
// current position.
- ElementListIter FindLowerBound(unsigned ElementIndex) {
+ ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const {
+
+ // We cache a non-const iterator so we're forced to resort to const_cast to
+ // get the begin/end in the case where 'this' is const. To avoid duplication
+ // of code with the only difference being whether the const cast is present
+ // 'this' is always const in this particular function and we sort out the
+ // difference in FindLowerBound and FindLowerBoundConst.
+ ElementListIter Begin =
+ const_cast<SparseBitVector<ElementSize> *>(this)->Elements.begin();
+ ElementListIter End =
+ const_cast<SparseBitVector<ElementSize> *>(this)->Elements.end();
if (Elements.empty()) {
- CurrElementIter = Elements.begin();
- return Elements.begin();
+ CurrElementIter = Begin;
+ return CurrElementIter;
}
// Make sure our current iterator is valid.
- if (CurrElementIter == Elements.end())
+ if (CurrElementIter == End)
--CurrElementIter;
// Search from our current iterator, either backwards or forwards,
@@ -284,17 +296,23 @@ class SparseBitVector {
if (CurrElementIter->index() == ElementIndex) {
return ElementIter;
} else if (CurrElementIter->index() > ElementIndex) {
- while (ElementIter != Elements.begin()
+ while (ElementIter != Begin
&& ElementIter->index() > ElementIndex)
--ElementIter;
} else {
- while (ElementIter != Elements.end() &&
+ while (ElementIter != End &&
ElementIter->index() < ElementIndex)
++ElementIter;
}
CurrElementIter = ElementIter;
return ElementIter;
}
+ ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const {
+ return FindLowerBoundImpl(ElementIndex);
+ }
+ ElementListIter FindLowerBound(unsigned ElementIndex) {
+ return FindLowerBoundImpl(ElementIndex);
+ }
// Iterator to walk set bits in the bitmap. This iterator is a lot uglier
// than it would be, in order to be efficient.
@@ -423,22 +441,12 @@ class SparseBitVector {
public:
using iterator = SparseBitVectorIterator;
- SparseBitVector() {
- CurrElementIter = Elements.begin();
- }
+ SparseBitVector() : Elements(), CurrElementIter(Elements.begin()) {}
- // SparseBitVector copy ctor.
- SparseBitVector(const SparseBitVector &RHS) {
- ElementListConstIter ElementIter = RHS.Elements.begin();
- while (ElementIter != RHS.Elements.end()) {
- Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter));
- ++ElementIter;
- }
-
- CurrElementIter = Elements.begin ();
- }
-
- ~SparseBitVector() = default;
+ SparseBitVector(const SparseBitVector &RHS)
+ : Elements(RHS.Elements), CurrElementIter(Elements.begin()) {}
+ SparseBitVector(SparseBitVector &&RHS)
+ : Elements(std::move(RHS.Elements)), CurrElementIter(Elements.begin()) {}
// Clear.
void clear() {
@@ -450,26 +458,23 @@ public:
if (this == &RHS)
return *this;
- Elements.clear();
-
- ElementListConstIter ElementIter = RHS.Elements.begin();
- while (ElementIter != RHS.Elements.end()) {
- Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter));
- ++ElementIter;
- }
-
- CurrElementIter = Elements.begin ();
-
+ Elements = RHS.Elements;
+ CurrElementIter = Elements.begin();
+ return *this;
+ }
+ SparseBitVector &operator=(SparseBitVector &&RHS) {
+ Elements = std::move(RHS.Elements);
+ CurrElementIter = Elements.begin();
return *this;
}
// Test, Reset, and Set a bit in the bitmap.
- bool test(unsigned Idx) {
+ bool test(unsigned Idx) const {
if (Elements.empty())
return false;
unsigned ElementIndex = Idx / ElementSize;
- ElementListIter ElementIter = FindLowerBound(ElementIndex);
+ ElementListConstIter ElementIter = FindLowerBoundConst(ElementIndex);
// If we can't find an element that is supposed to contain this bit, there
// is nothing more to do.
diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h
index 71b0e7527cb7..60a03633a8a6 100644
--- a/include/llvm/ADT/StringExtras.h
+++ b/include/llvm/ADT/StringExtras.h
@@ -139,22 +139,23 @@ inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
/// Convert buffer \p Input to its hexadecimal representation.
/// The returned string is double the size of \p Input.
-inline std::string toHex(StringRef Input) {
+inline std::string toHex(StringRef Input, bool LowerCase = false) {
static const char *const LUT = "0123456789ABCDEF";
+ const uint8_t Offset = LowerCase ? 32 : 0;
size_t Length = Input.size();
std::string Output;
Output.reserve(2 * Length);
for (size_t i = 0; i < Length; ++i) {
const unsigned char c = Input[i];
- Output.push_back(LUT[c >> 4]);
- Output.push_back(LUT[c & 15]);
+ Output.push_back(LUT[c >> 4] | Offset);
+ Output.push_back(LUT[c & 15] | Offset);
}
return Output;
}
-inline std::string toHex(ArrayRef<uint8_t> Input) {
- return toHex(toStringRef(Input));
+inline std::string toHex(ArrayRef<uint8_t> Input, bool LowerCase = false) {
+ return toHex(toStringRef(Input), LowerCase);
}
inline uint8_t hexFromNibbles(char MSB, char LSB) {
diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index c95b16dd4e8c..e06a68e27317 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -55,12 +55,11 @@ public:
bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
hexagon, // Hexagon: hexagon
- mips, // MIPS: mips, mipsallegrex
- mipsel, // MIPSEL: mipsel, mipsallegrexel
- mips64, // MIPS64: mips64
- mips64el, // MIPS64EL: mips64el
+ mips, // MIPS: mips, mipsallegrex, mipsr6
+ mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el
+ mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6
+ mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el
msp430, // MSP430: msp430
- nios2, // NIOSII: nios2
ppc, // PPC: powerpc
ppc64, // PPC64: powerpc64, ppu
ppc64le, // PPC64LE: powerpc64le
@@ -101,6 +100,7 @@ public:
enum SubArchType {
NoSubArch,
+ ARMSubArch_v8_5a,
ARMSubArch_v8_4a,
ARMSubArch_v8_3a,
ARMSubArch_v8_2a,
@@ -125,7 +125,9 @@ public:
KalimbaSubArch_v3,
KalimbaSubArch_v4,
- KalimbaSubArch_v5
+ KalimbaSubArch_v5,
+
+ MipsSubArch_r6
};
enum VendorType {
UnknownVendor,
@@ -182,7 +184,10 @@ public:
Mesa3D,
Contiki,
AMDPAL, // AMD PAL Runtime
- LastOSType = AMDPAL
+ HermitCore, // HermitCore Unikernel/Multikernel
+ Hurd, // GNU/Hurd
+ WASI, // Experimental WebAssembly OS
+ LastOSType = WASI
};
enum EnvironmentType {
UnknownEnvironment,
@@ -578,9 +583,20 @@ public:
return getOS() == Triple::KFreeBSD;
}
+ /// Tests whether the OS is Hurd.
+ bool isOSHurd() const {
+ return getOS() == Triple::Hurd;
+ }
+
+ /// Tests whether the OS is WASI.
+ bool isOSWASI() const {
+ return getOS() == Triple::WASI;
+ }
+
/// Tests whether the OS uses glibc.
bool isOSGlibc() const {
- return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD) &&
+ return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD ||
+ getOS() == Triple::Hurd) &&
!isAndroid();
}
diff --git a/include/llvm/ADT/bit.h b/include/llvm/ADT/bit.h
new file mode 100644
index 000000000000..a4aba7b6a9ee
--- /dev/null
+++ b/include/llvm/ADT/bit.h
@@ -0,0 +1,59 @@
+//===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the C++20 <bit> header.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_BIT_H
+#define LLVM_ADT_BIT_H
+
+#include "llvm/Support/Compiler.h"
+#include <cstring>
+#include <type_traits>
+
+namespace llvm {
+
+// This implementation of bit_cast is different from the C++17 one in two ways:
+// - It isn't constexpr because that requires compiler support.
+// - It requires trivially-constructible To, to avoid UB in the implementation.
+template <typename To, typename From
+ , typename = typename std::enable_if<sizeof(To) == sizeof(From)>::type
+#if (__has_feature(is_trivially_constructible) && defined(_LIBCPP_VERSION)) || \
+ (defined(__GNUC__) && __GNUC__ >= 5)
+ , typename = typename std::is_trivially_constructible<To>::type
+#elif __has_feature(is_trivially_constructible)
+ , typename = typename std::enable_if<__is_trivially_constructible(To)>::type
+#else
+ // See comment below.
+#endif
+#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \
+ (defined(__GNUC__) && __GNUC__ >= 5)
+ , typename = typename std::enable_if<std::is_trivially_copyable<To>::value>::type
+ , typename = typename std::enable_if<std::is_trivially_copyable<From>::value>::type
+#elif __has_feature(is_trivially_copyable)
+ , typename = typename std::enable_if<__is_trivially_copyable(To)>::type
+ , typename = typename std::enable_if<__is_trivially_copyable(From)>::type
+#else
+ // This case is GCC 4.x. clang with libc++ or libstdc++ never get here. Unlike
+ // llvm/Support/type_traits.h's isPodLike we don't want to provide a
+ // good-enough answer here: developers in that configuration will hit
+ // compilation failures on the bots instead of locally. That's acceptable
+ // because it's very few developers, and only until we move past C++11.
+#endif
+>
+inline To bit_cast(const From &from) noexcept {
+ To to;
+ std::memcpy(&to, &from, sizeof(To));
+ return to;
+}
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h
index 549c5221173d..40e490cf7864 100644
--- a/include/llvm/ADT/iterator.h
+++ b/include/llvm/ADT/iterator.h
@@ -202,9 +202,7 @@ template <
typename ReferenceT = typename std::conditional<
std::is_same<T, typename std::iterator_traits<
WrappedIteratorT>::value_type>::value,
- typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type,
- // Don't provide these, they are mostly to act as aliases below.
- typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>>
+ typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type>
class iterator_adaptor_base
: public iterator_facade_base<DerivedT, IteratorCategoryT, T,
DifferenceTypeT, PointerT, ReferenceT> {
@@ -311,8 +309,10 @@ make_pointee_range(RangeT &&Range) {
template <typename WrappedIteratorT,
typename T = decltype(&*std::declval<WrappedIteratorT>())>
class pointer_iterator
- : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT, T>,
- WrappedIteratorT, T> {
+ : public iterator_adaptor_base<
+ pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT,
+ typename std::iterator_traits<WrappedIteratorT>::iterator_category,
+ T> {
mutable T Ptr;
public:
@@ -334,6 +334,34 @@ make_pointer_range(RangeT &&Range) {
PointerIteratorT(std::end(std::forward<RangeT>(Range))));
}
+// Wrapper iterator over iterator ItType, adding DataRef to the type of ItType,
+// to create NodeRef = std::pair<InnerTypeOfItType, DataRef>.
+template <typename ItType, typename NodeRef, typename DataRef>
+class WrappedPairNodeDataIterator
+ : public iterator_adaptor_base<
+ WrappedPairNodeDataIterator<ItType, NodeRef, DataRef>, ItType,
+ typename std::iterator_traits<ItType>::iterator_category, NodeRef,
+ std::ptrdiff_t, NodeRef *, NodeRef &> {
+ using BaseT = iterator_adaptor_base<
+ WrappedPairNodeDataIterator, ItType,
+ typename std::iterator_traits<ItType>::iterator_category, NodeRef,
+ std::ptrdiff_t, NodeRef *, NodeRef &>;
+
+ const DataRef DR;
+ mutable NodeRef NR;
+
+public:
+ WrappedPairNodeDataIterator(ItType Begin, const DataRef DR)
+ : BaseT(Begin), DR(DR) {
+ NR.first = DR;
+ }
+
+ NodeRef &operator*() const {
+ NR.second = *this->I;
+ return NR;
+ }
+};
+
} // end namespace llvm
#endif // LLVM_ADT_ITERATOR_H