Author: ericwf Date: Thu Jun 30 17:34:43 2016 New Revision: 274286 URL: http://llvm.org/viewvc/llvm-project?rev=274286&view=rev Log: Replace __make_tuple_indices implementation with superior implementation.
The previous __make_tuple_indices implementation caused O(N) instantiations and was pretty inefficient. The C++14 __make_integer_sequence implementation is much better, since it either uses a builtin to generate the sequence or a very nice Log8(N) implementation provided by richard smith. This patch moves the __make_integer_sequence implementation into __tuple and uses it to implement __make_tuple_indices. Since libc++ can't expose the name 'integer_sequence' in C++11 this patch also introduces a dummy type '__integer_sequence' which is used when generating the sequence. One the sequence is generated '__integer_sequence' can be converted into the required type; either '__tuple_indices' or 'integer_sequence'. Modified: libcxx/trunk/include/__tuple libcxx/trunk/include/utility Modified: libcxx/trunk/include/__tuple URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tuple?rev=274286&r1=274285&r2=274286&view=diff ============================================================================== --- libcxx/trunk/include/__tuple (original) +++ libcxx/trunk/include/__tuple Thu Jun 30 17:34:43 2016 @@ -68,6 +68,80 @@ template <class _Tp> struct __tuple_like // tuple specializations #if !defined(_LIBCPP_HAS_NO_VARIADICS) + +template <size_t...> struct __tuple_indices {}; + +template <class _IdxType, _IdxType... _Values> +struct __integer_sequence { + template <template <class _OIdxType, _OIdxType...> class _ToIndexSeq, class _ToIndexType> + using __convert = _ToIndexSeq<_ToIndexType, _Values...>; + + template <size_t _Sp> + using __to_tuple_indices = __tuple_indices<(_Values + _Sp)...>; +}; + +#if !__has_builtin(__make_integer_seq) || defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE) +namespace __detail { + +template<typename _Tp, size_t ..._Extra> struct __repeat; +template<typename _Tp, _Tp ..._Np, size_t ..._Extra> struct __repeat<__integer_sequence<_Tp, _Np...>, _Extra...> { + typedef __integer_sequence<_Tp, + _Np..., + sizeof...(_Np) + _Np..., + 2 * sizeof...(_Np) + _Np..., + 3 * sizeof...(_Np) + _Np..., + 4 * sizeof...(_Np) + _Np..., + 5 * sizeof...(_Np) + _Np..., + 6 * sizeof...(_Np) + _Np..., + 7 * sizeof...(_Np) + _Np..., + _Extra...> type; +}; + +template<size_t _Np> struct __parity; +template<size_t _Np> struct __make : __parity<_Np % 8>::template __pmake<_Np> {}; + +template<> struct __make<0> { typedef __integer_sequence<size_t> type; }; +template<> struct __make<1> { typedef __integer_sequence<size_t, 0> type; }; +template<> struct __make<2> { typedef __integer_sequence<size_t, 0, 1> type; }; +template<> struct __make<3> { typedef __integer_sequence<size_t, 0, 1, 2> type; }; +template<> struct __make<4> { typedef __integer_sequence<size_t, 0, 1, 2, 3> type; }; +template<> struct __make<5> { typedef __integer_sequence<size_t, 0, 1, 2, 3, 4> type; }; +template<> struct __make<6> { typedef __integer_sequence<size_t, 0, 1, 2, 3, 4, 5> type; }; +template<> struct __make<7> { typedef __integer_sequence<size_t, 0, 1, 2, 3, 4, 5, 6> type; }; + +template<> struct __parity<0> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type> {}; }; +template<> struct __parity<1> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 1> {}; }; +template<> struct __parity<2> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 2, _Np - 1> {}; }; +template<> struct __parity<3> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 3, _Np - 2, _Np - 1> {}; }; +template<> struct __parity<4> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; +template<> struct __parity<5> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; +template<> struct __parity<6> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; +template<> struct __parity<7> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 7, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; + +} // namespace detail + +#endif // !__has_builtin(__make_integer_seq) || defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE) + +#if __has_builtin(__make_integer_seq) +template <size_t _Ep, size_t _Sp> +using __make_indices_imp = + typename __make_integer_seq<__integer_sequence, size_t, _Ep - _Sp>::template + __to_tuple_indices<_Sp>; +#else +template <size_t _Ep, size_t _Sp> +using __make_indices_imp = + typename __detail::__make<_Ep - _Sp>::type::template __to_tuple_indices<_Sp>; + +#endif + +template <size_t _Ep, size_t _Sp = 0> +struct __make_tuple_indices +{ + static_assert(_Sp <= _Ep, "__make_tuple_indices input error"); + typedef __make_indices_imp<_Ep, _Sp> type; +}; + + template <class ..._Tp> class _LIBCPP_TYPE_VIS_ONLY tuple; template <class... _Tp> struct __tuple_like<tuple<_Tp...> > : true_type {}; @@ -149,31 +223,6 @@ get(const array<_Tp, _Size>&&) _NOEXCEPT #if !defined(_LIBCPP_HAS_NO_VARIADICS) -// __make_tuple_indices - -template <size_t...> struct __tuple_indices {}; - -template <size_t _Sp, class _IntTuple, size_t _Ep> -struct __make_indices_imp; - -template <size_t _Sp, size_t ..._Indices, size_t _Ep> -struct __make_indices_imp<_Sp, __tuple_indices<_Indices...>, _Ep> -{ - typedef typename __make_indices_imp<_Sp+1, __tuple_indices<_Indices..., _Sp>, _Ep>::type type; -}; - -template <size_t _Ep, size_t ..._Indices> -struct __make_indices_imp<_Ep, __tuple_indices<_Indices...>, _Ep> -{ - typedef __tuple_indices<_Indices...> type; -}; - -template <size_t _Ep, size_t _Sp = 0> -struct __make_tuple_indices -{ - static_assert(_Sp <= _Ep, "__make_tuple_indices input error"); - typedef typename __make_indices_imp<_Sp, __tuple_indices<>, _Ep>::type type; -}; // __tuple_types Modified: libcxx/trunk/include/utility URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?rev=274286&r1=274285&r2=274286&view=diff ============================================================================== --- libcxx/trunk/include/utility (original) +++ libcxx/trunk/include/utility Thu Jun 30 17:34:43 2016 @@ -741,63 +741,15 @@ template<size_t... _Ip> #if __has_builtin(__make_integer_seq) && !defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE) template <class _Tp, _Tp _Ep> -struct __make_integer_sequence -{ - typedef __make_integer_seq<integer_sequence, _Tp, _Ep> type; -}; +using __make_integer_sequence = __make_integer_seq<integer_sequence, _Tp, _Ep>; #else -namespace __detail { - -template<typename _Tp, size_t ..._Extra> struct __repeat; -template<typename _Tp, _Tp ..._Np, size_t ..._Extra> struct __repeat<integer_sequence<_Tp, _Np...>, _Extra...> { - typedef integer_sequence<_Tp, - _Np..., - sizeof...(_Np) + _Np..., - 2 * sizeof...(_Np) + _Np..., - 3 * sizeof...(_Np) + _Np..., - 4 * sizeof...(_Np) + _Np..., - 5 * sizeof...(_Np) + _Np..., - 6 * sizeof...(_Np) + _Np..., - 7 * sizeof...(_Np) + _Np..., - _Extra...> type; -}; - -template<size_t _Np> struct __parity; -template<size_t _Np> struct __make : __parity<_Np % 8>::template __pmake<_Np> {}; - -template<> struct __make<0> { typedef integer_sequence<size_t> type; }; -template<> struct __make<1> { typedef integer_sequence<size_t, 0> type; }; -template<> struct __make<2> { typedef integer_sequence<size_t, 0, 1> type; }; -template<> struct __make<3> { typedef integer_sequence<size_t, 0, 1, 2> type; }; -template<> struct __make<4> { typedef integer_sequence<size_t, 0, 1, 2, 3> type; }; -template<> struct __make<5> { typedef integer_sequence<size_t, 0, 1, 2, 3, 4> type; }; -template<> struct __make<6> { typedef integer_sequence<size_t, 0, 1, 2, 3, 4, 5> type; }; -template<> struct __make<7> { typedef integer_sequence<size_t, 0, 1, 2, 3, 4, 5, 6> type; }; - -template<> struct __parity<0> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type> {}; }; -template<> struct __parity<1> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 1> {}; }; -template<> struct __parity<2> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 2, _Np - 1> {}; }; -template<> struct __parity<3> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 3, _Np - 2, _Np - 1> {}; }; -template<> struct __parity<4> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; -template<> struct __parity<5> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; -template<> struct __parity<6> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; -template<> struct __parity<7> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 7, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; - -template<typename _Tp, typename _Up> struct __convert { - template<typename> struct __result; - template<_Tp ..._Np> struct __result<integer_sequence<_Tp, _Np...> > { typedef integer_sequence<_Up, _Np...> type; }; -}; -template<typename _Tp> struct __convert<_Tp, _Tp> { template<typename _Up> struct __result { typedef _Up type; }; }; - -} - template<typename _Tp, _Tp _Np> using __make_integer_sequence_unchecked = - typename __detail::__convert<size_t, _Tp>::template __result<typename __detail::__make<_Np>::type>::type; + typename __detail::__make<_Np>::type::template __convert<integer_sequence, _Tp>; template <class _Tp, _Tp _Ep> -struct __make_integer_sequence +struct __make_integer_sequence_checked { static_assert(is_integral<_Tp>::value, "std::make_integer_sequence can only be instantiated with an integral type" ); @@ -807,10 +759,13 @@ struct __make_integer_sequence typedef __make_integer_sequence_unchecked<_Tp, 0 <= _Ep ? _Ep : 0> type; }; +template <class _Tp, _Tp _Ep> +using __make_integer_sequence = typename __make_integer_sequence_checked<_Tp, _Ep>::type; + #endif template<class _Tp, _Tp _Np> - using make_integer_sequence = typename __make_integer_sequence<_Tp, _Np>::type; + using make_integer_sequence = __make_integer_sequence<_Tp, _Np>; template<size_t _Np> using make_index_sequence = make_integer_sequence<size_t, _Np>; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits