Go to the documentation of this file.
17 #ifndef LLVM_ADT_STLEXTRAS_H
18 #define LLVM_ADT_STLEXTRAS_H
27 #include "llvm/Config/abi-breaking.h"
35 #include <initializer_list>
40 #include <type_traits>
43 #ifdef EXPENSIVE_CHECKS
55 template <
typename RangeT>
58 template <
typename RangeT>
59 using ValueOfRange =
typename std::remove_reference<decltype(
74 using type =
typename std::add_lvalue_reference<
79 template <
typename...>
using void_t = void;
80 template <
class,
template <
class...>
class Op,
class...
Args>
struct detector {
83 template <
template <
class...>
class Op,
class...
Args>
96 template <
template <
class...>
class Op,
class...
Args>
100 template <
typename Callable,
typename...
Args>
102 decltype(std::declval<Callable &>()(std::declval<Args>()...));
106 template <
typename Callable,
typename...
Args>
113 template <typename T, bool isClass = std::is_class<T>::value>
117 template <
typename ClassType,
typename ReturnType,
typename...
Args>
120 enum { num_args =
sizeof...(Args) };
126 template <
size_t Index>
130 template <
typename ClassType,
typename ReturnType,
typename...
Args>
137 enum { num_args =
sizeof...(Args) };
156 template <
typename T,
typename... Ts>
161 template <
typename T,
typename... Ts>
166 template <
typename T,
typename... Us>
168 : std::integral_constant<bool, !is_one_of<T, Us...>::value &&
169 TypesAreDistinct<Us...>::value> {};
182 template <
typename... Ts>
184 : std::integral_constant<bool, detail::TypesAreDistinct<Ts...>::value> {};
197 template <
typename T,
typename U,
typename... Us>
199 : std::integral_constant<size_t, 1 + FirstIndexOfType<T, Us...>::value> {};
200 template <
typename T,
typename... Us>
206 template <
size_t I,
typename... Ts>
211 template <
typename EnumTy1,
typename EnumTy2,
212 typename UT1 = std::enable_if_t<std::is_enum<EnumTy1>::value,
213 std::underlying_type_t<EnumTy1>>,
214 typename UT2 = std::enable_if_t<std::is_enum<EnumTy2>::value,
215 std::underlying_type_t<EnumTy2>>>
217 return static_cast<UT1
>(
LHS) +
static_cast<UT2
>(
RHS);
224 namespace adl_detail {
228 template <
typename ContainerTy>
230 return begin(std::forward<ContainerTy>(container));
235 template <
typename ContainerTy>
236 decltype(
auto)
adl_end(ContainerTy &&container) {
237 return end(std::forward<ContainerTy>(container));
242 template <
typename T>
243 void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(
swap(std::declval<T>(),
244 std::declval<T>()))) {
245 swap(std::forward<T>(lhs), std::forward<T>(rhs));
250 template <
typename ContainerTy>
255 template <
typename ContainerTy>
256 decltype(
auto)
adl_end(ContainerTy &&container) {
260 template <
typename T>
267 template <
typename T>
268 constexpr
bool empty(
const T &RangeOrContainer) {
275 return B !=
E && std::next(
B) ==
E;
280 template <
typename T>
auto drop_begin(T &&RangeOrContainer,
size_t N = 1) {
287 template <
typename T>
auto drop_end(T &&RangeOrContainer,
size_t N = 1) {
289 std::prev(
adl_end(RangeOrContainer),
N));
295 template <
typename ItTy,
typename FuncTy,
296 typename ReferenceTy =
297 decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
300 mapped_iterator<ItTy, FuncTy>, ItTy,
301 typename std::iterator_traits<ItTy>::iterator_category,
302 std::remove_reference_t<ReferenceTy>,
303 typename std::iterator_traits<ItTy>::difference_type,
304 std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
321 template <
class ItTy,
class FuncTy>
326 template <
class ContainerTy,
class FuncTy>
336 template <
typename DerivedT,
typename ItTy,
typename ReferenceTy>
340 typename std::iterator_traits<ItTy>::iterator_category,
341 std::remove_reference_t<ReferenceTy>,
342 typename std::iterator_traits<ItTy>::difference_type,
343 std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
353 return static_cast<const DerivedT &
>(*this).mapElement(*this->I);
362 template <
typename Inner>
363 static yes& test(Inner *
I, decltype(
I->rbegin()) * =
nullptr);
366 static no&
test(...);
369 static const bool value =
sizeof(test<Ty>(
nullptr)) ==
sizeof(yes);
373 template <
typename Ty>
379 template <
typename ContainerTy>
388 template <
typename ContainerTy>
411 template <
typename WrappedIteratorT,
typename PredicateT,
typename IterTag>
414 filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
416 typename std::common_type<
417 IterTag, typename std::iterator_traits<
418 WrappedIteratorT>::iterator_category>::type> {
426 while (this->I !=
End && !
Pred(*this->I))
440 using BaseT::operator++;
448 decltype(
auto) operator*()
const {
453 decltype(
auto) operator->()
const {
455 return BaseT::operator->();
461 typename IterTag = std::forward_iterator_tag>
471 template <
typename WrappedIteratorT,
typename PredicateT>
473 std::bidirectional_iterator_tag>
475 std::bidirectional_iterator_tag> {
478 void findPrevValid() {
479 while (!this->
Pred(*this->I))
484 using BaseT::operator--;
500 using type = std::forward_iterator_tag;
504 using type = std::bidirectional_iterator_tag;
512 std::bidirectional_iterator_tag,
513 typename std::iterator_traits<IterT>::iterator_category>::value>
::type;
520 template <
typename WrappedIteratorT,
typename PredicateT>
532 template <
typename RangeT,
typename PredicateT>
535 using FilterIteratorT =
538 FilterIteratorT(
std::begin(std::forward<RangeT>(Range)),
539 std::end(std::forward<RangeT>(Range)), Pred),
540 FilterIteratorT(
std::end(std::forward<RangeT>(Range)),
541 std::end(std::forward<RangeT>(Range)), Pred));
561 template <
typename WrappedIteratorT>
564 WrappedIteratorT, std::input_iterator_tag> {
570 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
571 bool IsEarlyIncremented =
false;
577 using BaseT::operator*;
578 decltype(*std::declval<WrappedIteratorT>()) operator*() {
579 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
580 assert(!IsEarlyIncremented &&
"Cannot dereference twice!");
581 IsEarlyIncremented =
true;
586 using BaseT::operator++;
588 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
589 assert(IsEarlyIncremented &&
"Cannot increment before dereferencing!");
590 IsEarlyIncremented =
false;
597 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
598 assert(!
LHS.IsEarlyIncremented &&
"Cannot compare after dereferencing!");
600 return (
const BaseT &)
LHS == (
const BaseT &)
RHS;
616 template <
typename RangeT>
617 iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>>
619 using EarlyIncIteratorT =
622 EarlyIncIteratorT(
std::end(std::forward<RangeT>(Range))));
626 template <
typename R,
typename UnaryPredicate>
627 bool all_of(R &&range, UnaryPredicate
P);
628 template <
typename R,
typename UnaryPredicate>
629 bool any_of(R &&range, UnaryPredicate
P);
638 using type = std::tuple<decltype(*declval<Iters>())...>;
641 template <
typename ZipType,
typename... Iters>
643 ZipType,
typename std::common_type<std::bidirectional_iterator_tag,
644 typename std::iterator_traits<
645 Iters>::iterator_category...>
::type,
648 typename std::iterator_traits<
typename std::tuple_element<
649 0, std::tuple<Iters...>>
::type>::difference_type,
657 template <
typename ZipType,
typename... Iters>
669 template <
size_t... Ns>
671 return std::tuple<Iters...>(std::next(std::get<Ns>(
iterators))...);
674 template <
size_t... Ns>
676 return std::tuple<Iters...>(std::prev(std::get<Ns>(
iterators))...);
679 template <
size_t... Ns>
681 std::index_sequence<Ns...>)
const {
682 return all_of(std::initializer_list<bool>{std::get<Ns>(this->
iterators) ==
691 return deref(std::index_sequence_for<Iters...>{});
696 return *
reinterpret_cast<ZipType *
>(
this);
701 "All inner iterators must be at least bidirectional.");
703 return *
reinterpret_cast<ZipType *
>(
this);
712 template <
typename... Iters>
723 template <
typename... Iters>
725 template <
size_t... Ns>
727 std::index_sequence<Ns...>)
const {
728 return all_of(std::initializer_list<bool>{std::get<Ns>(this->
iterators) !=
739 return !
test(other, std::index_sequence_for<Iters...>{});
743 template <
template <
typename...>
class ItType,
typename...
Args>
class zippy {
745 using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>;
753 std::tuple<
Args...> ts;
755 template <
size_t... Ns>
756 iterator begin_impl(std::index_sequence<Ns...>)
const {
759 template <
size_t... Ns>
iterator end_impl(std::index_sequence<Ns...>)
const {
767 return begin_impl(std::index_sequence_for<Args...>{});
769 iterator end()
const {
return end_impl(std::index_sequence_for<Args...>{}); }
775 template <
typename T,
typename U,
typename...
Args>
779 std::forward<T>(
t), std::forward<U>(u), std::forward<Args>(args)...);
784 template <
typename T,
typename U,
typename...
Args>
788 std::forward<T>(
t), std::forward<U>(u), std::forward<Args>(args)...);
792 template <
typename Iter>
799 template <
typename Iter>
801 std::remove_const_t<std::remove_reference_t<decltype(*
I)>>> {
809 llvm::Optional<
typename std::remove_const<
typename std::remove_reference<
817 template <
typename... Iters>
820 zip_longest_iterator<Iters...>,
821 typename std::common_type<
822 std::forward_iterator_tag,
823 typename std::iterator_traits<Iters>::iterator_category...>::type,
824 typename ZipLongestTupleType<Iters...>::type,
825 typename std::iterator_traits<typename std::tuple_element<
826 0, std::tuple<Iters...>>::type>::difference_type,
827 typename ZipLongestTupleType<Iters...>::type *,
828 typename ZipLongestTupleType<Iters...>::type> {
833 std::tuple<Iters...> iterators;
834 std::tuple<Iters...> end_iterators;
836 template <
size_t... Ns>
838 std::index_sequence<Ns...>)
const {
840 std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
841 std::get<Ns>(other.iterators)...},
845 template <
size_t... Ns>
value_type deref(std::index_sequence<Ns...>)
const {
847 deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
850 template <
size_t... Ns>
851 decltype(iterators) tup_inc(std::index_sequence<Ns...>)
const {
852 return std::tuple<Iters...>(
853 next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
858 : iterators(
std::forward<Iters>(ts.first)...),
859 end_iterators(
std::forward<Iters>(ts.second)...) {}
862 return deref(std::index_sequence_for<Iters...>{});
866 iterators = tup_inc(std::index_sequence_for<Iters...>{});
871 return !
test(other, std::index_sequence_for<Iters...>{});
886 std::tuple<
Args...> ts;
888 template <
size_t... Ns>
889 iterator begin_impl(std::index_sequence<Ns...>)
const {
891 adl_end(std::get<Ns>(ts)))...);
894 template <
size_t... Ns>
iterator end_impl(std::index_sequence<Ns...>)
const {
896 adl_end(std::get<Ns>(ts)))...);
903 return begin_impl(std::index_sequence_for<Args...>{});
905 iterator end()
const {
return end_impl(std::index_sequence_for<Args...>{}); }
912 template <
typename T,
typename U,
typename...
Args>
916 std::forward<T>(
t), std::forward<U>(u), std::forward<Args>(args)...);
929 template <
typename ValueT,
typename... IterTs>
932 std::forward_iterator_tag, ValueT> {
933 using BaseT =
typename concat_iterator::iterator_facade_base;
941 std::tuple<IterTs...> Begins;
942 std::tuple<IterTs...> Ends;
948 template <
size_t Index>
bool incrementHelper() {
949 auto &Begin = std::get<Index>(Begins);
950 auto &End = std::get<Index>(Ends);
961 template <
size_t... Ns>
void increment(std::index_sequence<Ns...>) {
964 &concat_iterator::incrementHelper<Ns>...};
967 for (
auto &IncrementHelperFn : IncrementHelperFns)
968 if ((this->*IncrementHelperFn)())
977 template <
size_t Index>
ValueT *getHelper()
const {
978 auto &Begin = std::get<Index>(Begins);
979 auto &End = std::get<Index>(Ends);
990 template <
size_t... Ns>
ValueT &get(std::index_sequence<Ns...>)
const {
993 &concat_iterator::getHelper<Ns>...};
996 for (
auto &GetHelperFn : GetHelperFns)
997 if (
ValueT *
P = (this->*GetHelperFn)())
1000 llvm_unreachable(
"Attempted to get a pointer from an end concat iterator!");
1008 template <
typename... RangeTs>
1012 using BaseT::operator++;
1015 increment(std::index_sequence_for<IterTs...>());
1020 return get(std::index_sequence_for<IterTs...>());
1024 return Begins ==
RHS.Begins && Ends ==
RHS.Ends;
1042 std::tuple<RangeTs...> Ranges;
1044 template <
size_t... Ns>
1045 iterator begin_impl(std::index_sequence<Ns...>) {
1046 return iterator(std::get<Ns>(Ranges)...);
1048 template <
size_t... Ns>
1049 iterator begin_impl(std::index_sequence<Ns...>)
const {
1050 return iterator(std::get<Ns>(Ranges)...);
1052 template <
size_t... Ns>
iterator end_impl(std::index_sequence<Ns...>) {
1054 std::end(std::get<Ns>(Ranges)))...);
1056 template <
size_t... Ns>
iterator end_impl(std::index_sequence<Ns...>)
const {
1058 std::end(std::get<Ns>(Ranges)))...);
1063 : Ranges(
std::forward<RangeTs>(Ranges)...) {}
1066 return begin_impl(std::index_sequence_for<RangeTs...>{});
1069 return begin_impl(std::index_sequence_for<RangeTs...>{});
1072 return end_impl(std::index_sequence_for<RangeTs...>{});
1075 return end_impl(std::index_sequence_for<RangeTs...>{});
1084 template <
typename ValueT,
typename... RangeTs>
1086 static_assert(
sizeof...(RangeTs) > 1,
1087 "Need more than one range to concatenate!");
1089 std::forward<RangeTs>(Ranges)...);
1094 template <
typename DerivedT,
typename BaseT,
typename T,
1095 typename PointerT =
T *,
typename ReferenceT =
T &>
1098 std::random_access_iterator_tag, T,
1099 std::ptrdiff_t, PointerT, ReferenceT> {
1114 this->
index += offset;
1115 return static_cast<DerivedT &
>(*this);
1118 this->
index -= offset;
1119 return static_cast<DerivedT &
>(*this);
1146 template <
typename DerivedT,
typename BaseT,
typename T,
1147 typename PointerT =
T *,
typename ReferenceT =
T &>
1154 PointerT, ReferenceT> {
1158 return DerivedT::dereference_iterator(this->
getBase(), this->
getIndex());
1190 return (*
this)[
size() - 1];
1194 template <
typename OtherT>
1196 const OtherT &rhs) {
1199 template <
typename OtherT>
1201 const OtherT &rhs) {
1202 return !(lhs == rhs);
1213 assert(
n + m <=
size() &&
"invalid size specifiers");
1214 return DerivedT(offset_base(
base,
n), m);
1219 assert(
size() >=
n &&
"Dropping more elements than exist");
1224 assert(
size() >=
n &&
"Dropping more elements than exist");
1231 :
static_cast<const DerivedT &
>(*this);
1237 :
static_cast<const DerivedT &
>(*this);
1241 template <
typename RangeT,
typename = std::enable_if_t<std::is_constructible<
1243 operator RangeT()
const {
1253 return n == 0 ?
base : DerivedT::offset_base(
base,
n);
1276 template <
typename DerivedT,
typename BaseT,
typename T,
1277 typename PointerT =
T *,
typename ReferenceT =
T &>
1280 DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT> {
1287 DerivedT, std::pair<BaseT, ptrdiff_t>,
T, PointerT,
1297 static std::pair<BaseT, ptrdiff_t>
1307 return DerivedT::dereference(
base.first,
base.second +
index);
1321 typename std::conditional_t<std::is_reference<EltTy>::value, FirstTy,
1322 std::remove_reference_t<FirstTy>>;
1331 EltTy, decltype((elt.first))>::
type {
1340 std::forward<ContainerTy>(
c),
1343 decltype((elt.second))>::
type {
1355 template <
typename T>
bool operator()(
const T &lhs,
const T &rhs)
const {
1356 return std::less<>()(lhs.first, rhs.first);
1363 template <
typename T>
bool operator()(
const T &lhs,
const T &rhs)
const {
1364 return std::less<>()(lhs.second, rhs.second);
1370 template<
typename FuncTy>
1374 template <
typename T>
1376 return func(lhs.first, rhs.first);
1387 template <
typename T,
typename... Ts>
1392 template <
typename T,
typename... Ts>
1398 template <
typename HeadT,
typename... TailTs>
1442 template <
typename... CallableTs>
1444 return detail::Visitor<CallableTs...>(std::forward<CallableTs>(Callables)...);
1453 template <
class Iterator,
class RNG>
1458 typename std::iterator_traits<Iterator>::difference_type difference_type;
1460 difference_type offset =
g() %
size;
1463 if (offset != difference_type(0))
1464 std::iter_swap(first, first + offset);
1469 template<
typename T>
1471 if (std::less<T>()(*
reinterpret_cast<const T*
>(P1),
1472 *
reinterpret_cast<const T*
>(
P2)))
1474 if (std::less<T>()(*
reinterpret_cast<const T*
>(
P2),
1475 *
reinterpret_cast<const T*
>(P1)))
1482 template<
typename T>
1484 (
const void*,
const void*) {
1485 return array_pod_sort_comparator<T>;
1488 #ifdef EXPENSIVE_CHECKS
1491 inline unsigned presortShuffleEntropy() {
1492 static unsigned Result(std::random_device{}());
1496 template <
class IteratorTy>
1497 inline void presortShuffle(IteratorTy Start, IteratorTy End) {
1498 std::mt19937 Generator(presortShuffleEntropy());
1519 template<
class IteratorTy>
1523 auto NElts = End - Start;
1524 if (NElts <= 1)
return;
1525 #ifdef EXPENSIVE_CHECKS
1526 detail::presortShuffle<IteratorTy>(Start, End);
1531 template <
class IteratorTy>
1533 IteratorTy Start, IteratorTy End,
1535 const typename std::iterator_traits<IteratorTy>::value_type *,
1536 const typename std::iterator_traits<IteratorTy>::value_type *)) {
1539 auto NElts = End - Start;
1540 if (NElts <= 1)
return;
1541 #ifdef EXPENSIVE_CHECKS
1542 detail::presortShuffle<IteratorTy>(Start, End);
1544 qsort(&*Start, NElts,
sizeof(*Start),
1545 reinterpret_cast<int (*)(
const void *,
const void *)
>(
Compare));
1549 template <
typename T>
1554 std::is_trivially_copyable<typename std::iterator_traits<T>::value_type>>;
1559 template <
typename IteratorTy,
1560 std::enable_if_t<!detail::sort_trivially_copyable<IteratorTy>::value,
1562 inline void sort(IteratorTy Start, IteratorTy End) {
1563 #ifdef EXPENSIVE_CHECKS
1564 detail::presortShuffle<IteratorTy>(Start, End);
1571 template <
typename IteratorTy,
1572 std::enable_if_t<detail::sort_trivially_copyable<IteratorTy>::value,
1574 inline void sort(IteratorTy Start, IteratorTy End) {
1578 template <
typename Container>
inline void sort(Container &&
C) {
1582 template <
typename IteratorTy,
typename Compare>
1584 #ifdef EXPENSIVE_CHECKS
1585 detail::presortShuffle<IteratorTy>(Start, End);
1590 template <
typename Container,
typename Compare>
1597 template <
typename R>
1600 std::is_base_of<std::random_access_iterator_tag,
1601 typename std::iterator_traits<decltype(
1602 Range.begin())>::iterator_category>::value,
1603 void> * =
nullptr) {
1604 return std::distance(Range.begin(), Range.end());
1609 template <
typename R,
typename UnaryFunction>
1616 template <
typename R,
typename UnaryPredicate>
1623 template <
typename R,
typename UnaryPredicate>
1630 template <
typename R,
typename UnaryPredicate>
1637 template <
typename R,
typename T>
auto find(R &&Range,
const T &Val) {
1643 template <
typename R,
typename UnaryPredicate>
1648 template <
typename R,
typename UnaryPredicate>
1655 template <
typename R,
typename UnaryPredicate>
1662 template <
typename R,
typename OutputIt,
typename UnaryPredicate>
1663 OutputIt
copy_if(R &&Range, OutputIt Out, UnaryPredicate
P) {
1667 template <
typename R,
typename OutputIt>
1668 OutputIt
copy(R &&Range, OutputIt Out) {
1674 template <
typename R,
typename OutputIt>
1675 OutputIt
move(R &&Range, OutputIt Out) {
1681 template <
typename R,
typename E>
1686 template <
typename T>
1709 template <
typename R,
typename E>
auto count(R &&Range,
const E &Element) {
1715 template <
typename R,
typename UnaryPredicate>
1722 template <
typename R,
typename OutputIt,
typename UnaryFunction>
1723 OutputIt
transform(R &&Range, OutputIt d_first, UnaryFunction
F) {
1729 template <
typename R,
typename UnaryPredicate>
1738 std::forward<T>(
Value));
1741 template <
typename R,
typename T,
typename Compare>
1744 std::forward<T>(
Value),
C);
1751 std::forward<T>(
Value));
1754 template <
typename R,
typename T,
typename Compare>
1757 std::forward<T>(
Value),
C);
1760 template <
typename R>
1765 template <
typename R,
typename Compare>
1772 template <
typename R,
typename Predicate,
1773 typename Val = decltype(*
adl_begin(std::declval<R>()))>
1778 template<
typename Range,
typename Predicate>
1785 template <
typename L,
typename R>
bool equal(L &&LRange, R &&RRange) {
1792 template <
typename R>
1794 size_t range_size =
size(Range);
1795 return range_size != 0 && (range_size == 1 ||
1806 template <
typename Container,
typename UnaryPredicate>
1814 template <
typename Container,
typename ValueType>
1822 template <
typename Container,
typename Range>
1824 C.insert(
C.end(), R.begin(), R.end());
1829 template<
typename Container,
typename RandomAccessIterator>
1830 void replace(Container &Cont,
typename Container::iterator ContIt,
1831 typename Container::iterator ContEnd, RandomAccessIterator ValIt,
1832 RandomAccessIterator ValEnd) {
1834 if (ValIt == ValEnd) {
1835 Cont.erase(ContIt, ContEnd);
1837 }
else if (ContIt == ContEnd) {
1838 Cont.insert(ContIt, ValIt, ValEnd);
1841 *ContIt++ = *ValIt++;
1847 template<
typename Container,
typename Range = std::initializer_list<
1848 typename Container::value_type>>
1849 void replace(Container &Cont,
typename Container::iterator ContIt,
1850 typename Container::iterator ContEnd, Range R) {
1851 replace(Cont, ContIt, ContEnd, R.begin(), R.end());
1864 template <
typename ForwardIterator,
typename UnaryFunctor,
1865 typename NullaryFunctor,
1866 typename =
typename std::enable_if<
1867 !std::is_constructible<StringRef, UnaryFunctor>::value &&
1868 !std::is_constructible<StringRef, NullaryFunctor>::value>
::type>
1870 UnaryFunctor each_fn, NullaryFunctor between_fn) {
1881 template <
typename Container,
typename UnaryFunctor,
typename NullaryFunctor,
1882 typename =
typename std::enable_if<
1883 !std::is_constructible<StringRef, UnaryFunctor>::value &&
1884 !std::is_constructible<StringRef, NullaryFunctor>::value>
::type>
1886 NullaryFunctor between_fn) {
1891 template <
typename Container,
typename UnaryFunctor,
typename StreamT,
1892 typename T = detail::ValueOfRange<Container>>
1893 inline void interleave(
const Container &
c, StreamT &os, UnaryFunctor each_fn,
1895 interleave(
c.begin(),
c.end(), each_fn, [&] { os << separator; });
1897 template <
typename Container,
typename StreamT,
1898 typename T = detail::ValueOfRange<Container>>
1902 c, os, [&](
const T &
a) { os <<
a; }, separator);
1905 template <
typename Container,
typename UnaryFunctor,
typename StreamT,
1906 typename T = detail::ValueOfRange<Container>>
1908 UnaryFunctor each_fn) {
1911 template <
typename Container,
typename StreamT,
1912 typename T = detail::ValueOfRange<Container>>
1927 template<
typename First,
typename Second>
1930 return std::hash<First>()(
P.first) * 31 + std::hash<Second>()(
P.second);
1942 template <
typename A,
typename B>
auto operator()(A &lhs,
B &rhs)
const {
1945 return func(*lhs, *rhs);
1955 typename std::iterator_traits<IterOfRange<R>>::reference;
1979 template <
typename R>
1980 class enumerator_iter
1982 const result_pair<R>> {
1983 using result_type = result_pair<R>;
1987 : Result(
std::numeric_limits<
size_t>::
max(), EndIter) {}
1990 : Result(
Index, Iter) {}
2005 return Result.Iter ==
RHS.Result.Iter;
2010 Result =
Other.Result;
2063 template <
typename F,
typename Tuple, std::size_t...
I>
2065 return std::forward<F>(
f)(std::get<I>(std::forward<Tuple>(
t))...);
2073 template <
typename F,
typename Tuple>
2075 using Indices = std::make_index_sequence<
2086 auto z =
zip(args...);
2087 auto it =
z.begin();
2090 if (!
apply_tuple([&](
auto &&...args) {
return P(args...); }, *
it))
2094 return it.all_equals(
end);
2099 template <
typename... ArgsThenPredicate,
size_t... InputIndexes>
2101 std::tuple<ArgsThenPredicate...> argsThenPredicate,
2102 std::index_sequence<InputIndexes...>) {
2103 auto constexpr OutputIndex =
2104 std::tuple_size<decltype(argsThenPredicate)>::value - 1;
2106 std::get<InputIndexes>(argsThenPredicate)...);
2114 template <
typename... ArgsAndPredicate>
2117 std::forward_as_tuple(argsAndPredicate...),
2118 std::make_index_sequence<
sizeof...(argsAndPredicate) - 1>{});
2124 template <
typename IterTy,
2125 typename Pred = bool (*)(
const decltype(*std::declval<IterTy>()) &)>
2127 IterTy &&Begin, IterTy &&End,
unsigned N,
2128 Pred &&ShouldBeCounted =
2129 [](
const decltype(*std::declval<IterTy>()) &) {
return true; },
2131 !std::is_base_of<std::random_access_iterator_tag,
2132 typename std::iterator_traits<std::remove_reference_t<
2133 decltype(Begin)>>::iterator_category>::value,
2134 void> * =
nullptr) {
2135 for (;
N; ++Begin) {
2138 N -= ShouldBeCounted(*Begin);
2140 for (; Begin != End; ++Begin)
2141 if (ShouldBeCounted(*Begin))
2149 template <
typename IterTy,
2150 typename Pred = bool (*)(
const decltype(*std::declval<IterTy>()) &)>
2152 IterTy &&Begin, IterTy &&End,
unsigned N,
2153 Pred &&ShouldBeCounted =
2154 [](
const decltype(*std::declval<IterTy>()) &) {
return true; },
2156 !std::is_base_of<std::random_access_iterator_tag,
2157 typename std::iterator_traits<std::remove_reference_t<
2158 decltype(Begin)>>::iterator_category>::value,
2159 void> * =
nullptr) {
2160 for (;
N; ++Begin) {
2163 N -= ShouldBeCounted(*Begin);
2170 template <
typename IterTy,
2171 typename Pred = bool (*)(
const decltype(*std::declval<IterTy>()) &)>
2173 IterTy &&Begin, IterTy &&End,
unsigned N,
2174 Pred &&ShouldBeCounted = [](
const decltype(*std::declval<IterTy>()) &) {
2182 template <
typename ContainerTy>
bool hasNItems(ContainerTy &&
C,
unsigned N) {
2187 template <
typename ContainerTy>
2193 template <
typename ContainerTy>
2205 template <
class Ptr>
auto to_address(
const Ptr &
P) {
return P.operator->(); }
2210 #endif // LLVM_ADT_STLEXTRAS_H
zip_first(Iters &&... ts)
typename iterator::pointer pointer
size_t size() const
Return the size of this range.
RTTIExtends< ObjectLinkingLayer, ObjectLayer > BaseT
bool hasNItemsOrLess(IterTy &&Begin, IterTy &&End, unsigned N, Pred &&ShouldBeCounted=[](const decltype(*std::declval< IterTy >()) &) { return true;})
Returns true if the sequence [Begin, End) has N or less items.
bool operator==(const enumerator_iter &RHS) const
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
enumerator_iter< R > end()
Function object to check whether the second component of a std::pair compares less than the second co...
typename std::remove_reference< decltype(*std::begin(std::declval< RangeT & >()))>::type ValueOfRange
This is an optimization pass for GlobalISel generic memory operations.
filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred)
mapped_iterator_base(ItTy U)
bool empty() const
Return if the range is empty.
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
ReferenceTy operator*() const
into xmm2 addss xmm2 xmm1 xmm3 addss xmm3 movaps xmm0 unpcklps xmm0 ret seems silly when it could just be one addps Expand libm rounding functions main should enable SSE DAZ mode and other fast SSE modes Think about doing i64 math in SSE regs on x86 This testcase should have no SSE instructions in it
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
decltype(std::begin(std::declval< RangeT & >())) IterOfRange
ptrdiff_t getStartIndex() const
Returns the current start index of the range.
bool operator==(const indexed_accessor_iterator &rhs) const
concat_iterator(RangeTs &&... Ranges)
Constructs an iterator from a sequence of ranges.
bool hasNItems(IterTy &&Begin, IterTy &&End, unsigned N, Pred &&ShouldBeCounted=[](const decltype(*std::declval< IterTy >()) &) { return true;}, std::enable_if_t< !std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< std::remove_reference_t< decltype(Begin)>>::iterator_category >::value, void > *=nullptr)
Return true if the sequence [Begin, End) has exactly N items.
zip_common(Iters &&... ts)
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Replace within non kernel function use of LDS with pointer
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
DerivedT & operator+=(ptrdiff_t offset)
ZipLongestTupleType< Iters... >::type * pointer
constexpr Visitor(HeadT &&Head, TailTs &&...Tail)
A base type of mapped iterator, that is useful for building derived iterators that do not need/want t...
DerivedT take_front(size_t n=1) const
Take the first n elements.
detail::enumerator< R > enumerate(R &&TheRange)
Given an input range, returns a new range whose values are are pair (A,B) such that A is the 0-based ...
bool is_sorted(R &&Range)
Wrapper function around std::is_sorted to check if elements in a range R are sorted in non-descending...
friend bool operator!=(const indexed_accessor_range_base &lhs, const OtherT &rhs)
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
bool operator<(const indexed_accessor_iterator &rhs) const
zip_longest_iterator< Iters... > & operator++()
void stable_sort(R &&Range, Compare C)
enumerator_iter(IterOfRange< R > EndIter)
constexpr Visitor(HeadT &&Head)
void interleaveComma(const Container &c, StreamT &os, UnaryFunctor each_fn)
void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval< T >(), std::declval< T >())))
Specialization of filter_iterator_base for forward iteration only.
DerivedT drop_front(size_t n=1) const
Drop the first n elements.
result_pair(const result_pair< R > &Other)
auto reverse(ContainerTy &&C, std::enable_if_t< has_rbegin< ContainerTy >::value > *=nullptr)
decltype(auto) apply_tuple_impl(F &&f, Tuple &&t, std::index_sequence< I... >)
bool test_all_equals(const zip_common &other, std::index_sequence< Ns... >) const
ItType< decltype(std::begin(std::declval< Args >()))... > iterator
const_iterator end(StringRef path)
Get end iterator over path.
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
CRTP base class for adapting an iterator to a different type.
iterator_adaptor_base()=default
OutputIt copy(R &&Range, OutputIt Out)
auto upper_bound(R &&Range, T &&Value, Compare C)
decltype(auto) apply_tuple(F &&f, Tuple &&t)
Given an input tuple (a1, a2, ..., an), pass the arguments of the tuple variadically to f as if by ca...
Expected< ExpressionValue > max(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
should just be implemented with a CLZ instruction Since there are other e g
Iterator wrapper that concatenates sequences together.
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
result_pair(std::size_t Index, IterOfRange< R > Iter)
detail::zippy< detail::zip_first, T, U, Args... > zip_first(T &&t, U &&u, Args &&... args)
zip iterator that, for the sake of efficiency, assumes the first iteratee to be the shortest.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
Metafunction to determine if T& or T has a member called rbegin().
zip_longest_iterator(std::pair< Iters &&, Iters && >... ts)
mapped_iterator< ItTy, FuncTy > map_iterator(ItTy I, FuncTy F)
typename iterator::pointer pointer
DerivedT drop_back(size_t n=1) const
Drop the last n elements.
is currently compiled esp esp jne LBB1_1 esp ret esp esp jne L_abort $stub esp ret This can be applied to any no return function call that takes no arguments etc the stack save restore logic could be shrink wrapped
typename detail::detector< void, Op, Args... >::value_t is_detected
Detects if a given trait holds for some set of arguments 'Args'.
static std::pair< BaseT, ptrdiff_t > offset_base(const std::pair< BaseT, ptrdiff_t > &base, ptrdiff_t index)
See detail::indexed_accessor_range_base for details.
=0.0 ? 0.0 :(a > 0.0 ? 1.0 :-1.0) a
filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred)
typename iterator::reference reference
filter_iterator_base & operator++()
typename std::add_lvalue_reference< typename std::add_const< T >::type >::type type
auto remove_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly.
typename iterator::value_type value_type
void interleave(ForwardIterator begin, ForwardIterator end, UnaryFunctor each_fn, NullaryFunctor between_fn)
An STL-style algorithm similar to std::for_each that applies a second functor between every pair of e...
typename ZipLongestTupleType< Iters... >::type value_type
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
std::tuple< typename ZipLongestItemType< Iters >::type... > type
const BaseT & getBase() const
Returns the current base of the range.
@ Tail
Tail - This calling convention attemps to make calls as fast as possible while guaranteeing that tail...
DerivedT slice(size_t n, size_t m) const
Drop the first N elements, and keep M elements.
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
Itanium Name Demangler i e convert the string _Z1fv into f()". You can also use the CRTP base ManglingParser to perform some simple analysis on the mangled name
A utility class used to implement an iterator that contains some base object and an index.
This might compile to this xmm1 xorps xmm0 movss xmm0 ret Now consider if the code caused xmm1 to get spilled This might produce this xmm1 movaps xmm0 movaps xmm1 movss xmm0 ret since the reload is only used by these we could fold it into the producing something like xmm1 movaps xmm0 ret saving two instructions The basic idea is that a reload from a spill if only one byte chunk is bring in zeros the one element instead of elements This can be used to simplify a variety of shuffle where the elements are fixed zeros This code generates ugly probably due to costs being off or< 4 x float > * P2
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
decltype(auto) adl_end(ContainerTy &&container)
ReturnType result_t
The result type of this function.
Function object to check whether the first component of a std::pair compares less than the first comp...
(vector float) vec_cmpeq(*A, *B) C
This class provides various trait information about a callable object.
typename iterator::difference_type difference_type
ValueT & operator*() const
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
const FuncTy & getFunction() const
const BaseT & getBase() const
Returns the current base of the iterator.
early_inc_iterator_impl & operator++()
value_type operator*() const
const result_type & operator*() const
bitcast float %x to i32 %s=and i32 %t, 2147483647 %d=bitcast i32 %s to float ret float %d } declare float @fabsf(float %n) define float @bar(float %x) nounwind { %d=call float @fabsf(float %x) ret float %d } This IR(from PR6194):target datalayout="e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple="x86_64-apple-darwin10.0.0" %0=type { double, double } %struct.float3=type { float, float, float } define void @test(%0, %struct.float3 *nocapture %res) nounwind noinline ssp { entry:%tmp18=extractvalue %0 %0, 0 t
A pseudo-iterator adaptor that is designed to implement "early increment" style loops.
void replace(Container &Cont, typename Container::iterator ContIt, typename Container::iterator ContEnd, RandomAccessIterator ValIt, RandomAccessIterator ValEnd)
Given a sequence container Cont, replace the range [ContIt, ContEnd) with the range [ValIt,...
std::size_t index() const
typename iterator::value_type value_type
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
BaseT base
The base that owns the provided range of values.
typename std::tuple_element< i, std::tuple< Args... > >::type arg_t
The type of an argument to this function.
indexed_accessor_range_base(iterator begin, iterator end)
friend bool operator==(const indexed_accessor_range_base &lhs, const OtherT &rhs)
Compare this range with another.
bool hasNItemsOrMore(IterTy &&Begin, IterTy &&End, unsigned N, Pred &&ShouldBeCounted=[](const decltype(*std::declval< IterTy >()) &) { return true;}, std::enable_if_t< !std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< std::remove_reference_t< decltype(Begin)>>::iterator_category >::value, void > *=nullptr)
Return true if the sequence [Begin, End) has N or more items.
enumerator_iter(std::size_t Index, IterOfRange< R > Iter)
bool operator()(const T &lhs, const T &rhs) const
enumerator_iter< R > end() const
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int int c
early_inc_iterator_impl(WrappedIteratorT I)
detail::zip_longest_range< T, U, Args... > zip_longest(T &&t, U &&u, Args &&... args)
Iterate over two or more iterators at the same time.
void erase_value(Container &C, ValueType V)
Wrapper function to remove a value from a container:
bool operator==(const zip_longest_iterator< Iters... > &other) const
int(*)(const void *, const void *) get_array_pod_sort_comparator(const T &)
get_array_pod_sort_comparator - This is an internal helper function used to get type deduction of T r...
ZipLongestTupleType< Iters... >::type reference
ReferenceT operator*() const
Find the first index where a type appears in a list of types.
constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS)
Helper which adds two underlying types of enumeration type.
result_pair & operator=(const result_pair &Other)
DerivedT take_back(size_t n=1) const
Take the last n elements.
Utility type to build an inheritance chain that makes it easy to rank overload candidates.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
typename std::iterator_traits< IterOfRange< R > >::reference value_reference
AMD64 Optimization Manual has some nice information about optimizing integer multiplication by a constant How much of it applies to Intel s X86 implementation There are definite trade offs to xmm0 cvttss2siq rdx jb L3 subss xmm0 rax cvttss2siq rdx xorq rdx rax ret instead of xmm1 cvttss2siq rcx movaps xmm2 subss xmm2 cvttss2siq rax rdx xorq rax ucomiss xmm0 cmovb rax ret Seems like the jb branch has high likelihood of being taken It would have saved a few instructions It s not possible to reference and DH registers in an instruction requiring REX prefix divb and mulb both produce results in AH If isel emits a CopyFromReg which gets turned into a movb and that can be allocated a r8b r15b To get around isel emits a CopyFromReg from AX and then right shift it down by and truncate it It s not pretty but it works We need some register allocation magic to make the hack go which would often require a callee saved register Callees usually need to keep this value live for most of their body so it doesn t add a significant burden on them We currently implement this in however this is suboptimal because it means that it would be quite awkward to implement the optimization for callers A better implementation would be to relax the LLVM IR rules for sret arguments to allow a function with an sret argument to have a non void return type
filter_iterator_impl & operator--()
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
bool equal(L &&LRange, R &&RRange)
Wrapper function around std::equal to detect if pair-wise elements between two ranges are the same.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
decltype(iterators) tup_inc(std::index_sequence< Ns... >) const
ReturnType result_t
The result type of this function.
auto lower_bound(R &&Range, T &&Value, Compare C)
ptrdiff_t count
The size from the owning range.
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
typename std::add_pointer< typename std::add_const< T >::type >::type type
DerivedT & operator-=(ptrdiff_t offset)
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
indexed_accessor_iterator(BaseT base, ptrdiff_t index)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
is_detected< detail::is_invocable, Callable, Args... > is_invocable
Check if a Callable type can be invoked with the given set of arg types.
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
constexpr decltype(auto) makeVisitor(CallableTs &&...Callables)
Returns an opaquely-typed Callable object whose operator() overload set is the sum of the operator() ...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&... Ranges)
Concatenated range across two or more ranges.
enumerator_iter & operator++()
std::tuple< decltype(*declval< Iters >())... > type
void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(adl_detail::adl_swap(std::declval< T >(), std::declval< T >())))
void shuffle(Iterator first, Iterator last, RNG &&g)
friend bool operator==(const early_inc_iterator_impl &LHS, const early_inc_iterator_impl &RHS)
bool operator()(const T &lhs, const T &rhs) const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
typename iterator::iterator_category iterator_category
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
auto to_address(const Ptr &P)
Returns a raw pointer that represents the same address as the argument.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
std::iterator_traits< std::tuple_element< 0, std::tuple< Iters... > >::type >::difference_type difference_type
enumerator_iter< R > begin() const
bool is_splat(R &&Range)
Wrapper function around std::equal to detect if all elements in a container are same.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&... args)
zip iterator for two or more iteratable types.
ReferenceTy operator*() const
enumerator_iter(const enumerator_iter &Other)
QP Compare Ordered outs ins xscmpudp No builtin are required Or llvm fcmp order unorder compare DP QP Compare builtin are required DP Compare
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
indexed_accessor_range_base(BaseT base, ptrdiff_t count)
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
bool hasSingleElement(ContainerTy &&C)
Returns true if the given container only contains a single element.
APInt operator*(APInt a, uint64_t RHS)
value_type deref(std::index_sequence< Ns... >) const
std::tuple_element_t< I, std::tuple< Ts... > > TypeAtIndex
Find the type at a given index in a list of types.
const BaseT & getBase() const
Returns the base of this range.
std::bidirectional_iterator_tag type
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
StringRef - Represent a constant reference to a string, i.e.
size_t operator()(const std::pair< First, Second > &P) const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Function object to apply a binary function to the first component of a std::pair.
Iter next_or_end(const Iter &I, const Iter &End)
zip_longest_range(Args &&... ts_)
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
indexed_accessor_range_base(const iterator_range< iterator > &range)
typename Base::value_type value_type
ptrdiff_t getIndex() const
Returns the current index of the iterator.
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
An iterator adaptor that filters the elements of given inner iterators.
ReferenceT operator[](size_t Index) const
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool all_of_zip_predicate_last(std::tuple< ArgsThenPredicate... > argsThenPredicate, std::index_sequence< InputIndexes... >)
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
typename fwd_or_bidi_tag_impl< std::is_base_of< std::bidirectional_iterator_tag, typename std::iterator_traits< IterT >::iterator_category >::value >::type type
auto map_range(ContainerTy &&C, FuncTy F)
void stable_sort(R &&Range)
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
bool all_of_zip_predicate_first(Predicate &&P, Args &&...args)
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
decltype(iterators) tup_dec(std::index_sequence< Ns... >) const
static ReferenceT dereference_iterator(const std::pair< BaseT, ptrdiff_t > &base, ptrdiff_t index)
See detail::indexed_accessor_range_base for details.
Helper to store a sequence of ranges being concatenated and access them.
indexed_accessor_range_base & operator=(const indexed_accessor_range_base &)=default
decltype(auto) adl_begin(ContainerTy &&container)
Helper to determine if type T has a member called rbegin().
decltype(auto) adl_begin(ContainerTy &&container)
std::forward_iterator_tag type
void sort(IteratorTy Start, IteratorTy End)
concat_iterator< ValueT, decltype(std::begin(std::declval< RangeTs & >()))... > iterator
filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred)
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
auto unique(Range &&R, Predicate P)
instcombine should handle this transform
bool all_of_zip(ArgsAndPredicate &&...argsAndPredicate)
Compare two zipped ranges using the provided predicate (as last argument).
Return a reference to the first or second member of a reference.
typename std::tuple_element< Index, std::tuple< Args... > >::type arg_t
The type of an argument to this function.
typename iterator::reference reference
concat_iterator & operator++()
An iterator element of this range.
concat_range(RangeTs &&... Ranges)
int array_pod_sort_comparator(const void *P1, const void *P2)
Adapt std::less<T> for array_pod_sort.
zip_longest_iterator< decltype(adl_begin(std::declval< Args >()))... > iterator
bool all_equals(zip_common &other)
Return true if all the iterator are matching other's iterators.
bool operator==(const concat_iterator &RHS) const
enumerator_iter & operator=(const enumerator_iter &Other)
enumerator_iter< R > begin()
A range adaptor for a pair of iterators.
The class represents the base of a range of indexed_accessor_iterators.
Helper which sets its type member to forward_iterator_tag if the category of IterT does not derive fr...
This class provides an implementation of a range of indexed_accessor_iterators where the base is not ...
bool operator==(const zip_shortest< Iters... > &other) const
ptrdiff_t operator-(const indexed_accessor_iterator &rhs) const
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
void sort(Container &&C, Compare Comp)
std::common_type< std::forward_iterator_tag, std::iterator_traits< Iters >::iterator_category... >::type iterator_category
indexed_accessor_range(BaseT base, ptrdiff_t startIndex, ptrdiff_t count)
auto operator()(A &lhs, B &rhs) const
value_reference value() const
The same transformation can work with an even modulo with the addition of a and shrink the compare RHS by the same amount Unless the target supports that transformation probably isn t worthwhile The transformation can also easily be made to work with non zero equality for n
we should consider alternate ways to model stack dependencies Lots of things could be done in WebAssemblyTargetTransformInfo cpp there are numerous optimization related hooks that can be overridden in WebAssemblyTargetLowering Instead of the OptimizeReturned which should consider preserving the returned attribute through to MachineInstrs and extending the MemIntrinsicResults pass to do this optimization on calls too That would also let the WebAssemblyPeephole pass clean up dead defs for such as it does for stores Consider implementing and or getMachineCombinerPatterns Find a clean way to fix the problem which leads to the Shrink Wrapping pass being run after the WebAssembly PEI pass When setting multiple variables to the same we currently get code like const It could be done with a smaller encoding like local tee $pop5 local copy
std::tuple< Iters... > iterators
value_type operator*() const
typename iterator::iterator_category iterator_category
auto deref_or_none(const Iter &I, const Iter &End) -> llvm::Optional< std::remove_const_t< std::remove_reference_t< decltype(*I)>>>
mapped_iterator(ItTy U, FuncTy F)
LLVM Value Representation.
Binary functor that adapts to any other binary functor after dereferencing operands.
decltype(auto) adl_end(ContainerTy &&container)
bool operator==(const zip_first< Iters... > &other) const
auto find_if_not(R &&Range, UnaryPredicate P)
typename iterator::difference_type difference_type
Determine if all types in Ts are distinct.
zip_shortest(Iters &&... ts)
Optional< std::vector< StOtherPiece > > Other
conjunction< std::is_pointer< T >, std::is_trivially_copyable< typename std::iterator_traits< T >::value_type > > sort_trivially_copyable
decltype(std::declval< Callable & >()(std::declval< Args >()...)) is_invocable
typename std::conditional_t< std::is_reference< EltTy >::value, FirstTy, std::remove_reference_t< FirstTy > > type