From 83aca35dde9ecc81044398a6d21a89d88a3f708f Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Tue, 26 Nov 2024 18:22:01 -0800 Subject: [PATCH] add a `__type_switch` utility and use it the ptx generator (#2946) --- docs/repo.toml | 5 +- .../functions/cuda_ptx_generated_helper.h | 92 +++++++------- libcudacxx/include/cuda/std/__cccl/dialect.h | 9 ++ .../cuda/std/__type_traits/type_list.h | 112 +++++++++++++++--- .../test/libcudacxx/cuda/type_list.pass.cpp | 20 ++++ 5 files changed, 168 insertions(+), 70 deletions(-) diff --git a/docs/repo.toml b/docs/repo.toml index f7c426f13db..ace31c74c71 100644 --- a/docs/repo.toml +++ b/docs/repo.toml @@ -149,6 +149,7 @@ doxygen_predefined = [ "_CCCL_FORCEINLINE", "_CCCL_STD_VER", "_CCCL_NODISCARD", + "_CCCL_NTTP_AUTO=auto", "_CCCL_VISIBILITY_HIDDEN", "_CCCL_SUPPRESS_DEPRECATED_PUSH", "_CCCL_SUPPRESS_DEPRECATED_POP", @@ -261,6 +262,7 @@ doxygen_predefined = [ "_CCCL_HOST=", "_CCCL_HOST_DEVICE=", "_CCCL_NODISCARD=[[nodiscard]]", + "_CCCL_NTTP_AUTO=auto", "_CCCL_STD_VER", "_CCCL_SUPPRESS_DEPRECATED_PUSH", "_CCCL_SUPPRESS_DEPRECATED_POP", @@ -408,6 +410,7 @@ doxygen_predefined = [ "_CCCL_CUDACC_AT_LEAST(x, y)=1", "_CCCL_CUDACC_BELOW(x, y)=0", "_CCCL_DEVICE=", + "_CCCL_DOXYGEN_INVOKED", "_CCCL_EAT_REST(x)=", "_CCCL_EXEC_CHECK_DISABLE=", "_CCCL_FORCEINLINE=", @@ -419,6 +422,7 @@ doxygen_predefined = [ "_CCCL_INLINE_VAR=inline", "_CCCL_NODISCARD=[[nodiscard]]", "_CCCL_NODISCARD_FRIEND=", + "_CCCL_NTTP_AUTO=auto", "_CCCL_STD_VER=2020", "_CCCL_TRAIT(x, y)=x::value", "_CUDA_VMR=cuda::mr", @@ -443,7 +447,6 @@ doxygen_predefined = [ "_CUDAX_TRIVIAL_DEVICE_API", "_CUDAX_PUBLIC_API", "LIBCUDACXX_ENABLE_EXPERIMENTAL_MEMORY_RESOURCE=", - "_CCCL_DOXYGEN_INVOKED", ] # make sure to use ./fetch_imgs.sh diff --git a/libcudacxx/include/cuda/std/__atomic/functions/cuda_ptx_generated_helper.h b/libcudacxx/include/cuda/std/__atomic/functions/cuda_ptx_generated_helper.h index 2e2266ce979..cdb35957509 100644 --- a/libcudacxx/include/cuda/std/__atomic/functions/cuda_ptx_generated_helper.h +++ b/libcudacxx/include/cuda/std/__atomic/functions/cuda_ptx_generated_helper.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -110,61 +111,50 @@ struct __atomic_longlong2 template using __atomic_cuda_deduce_bitwise = - _If, - _If, - _If, - _If, - __atomic_cuda_operand_deduction<__atomic_longlong2, __atomic_cuda_operand_b128>>>>>; + __type_switch>, + __type_case<2, __atomic_cuda_operand_deduction>, + __type_case<4, __atomic_cuda_operand_deduction>, + __type_case<8, __atomic_cuda_operand_deduction>, + __type_default<__atomic_cuda_operand_deduction<__atomic_longlong2, __atomic_cuda_operand_b128>>>; template -using __atomic_cuda_deduce_arithmetic = - _If<_CCCL_TRAIT(is_floating_point, _Type), - _If, - __atomic_cuda_operand_deduction>, - _If<_CCCL_TRAIT(is_signed, _Type), - _If, - _If, - _If, - __atomic_cuda_operand_deduction>>>, // There is no - // atom.add.s64 - _If, - _If, - _If, - __atomic_cuda_operand_deduction>>>>>; +using __atomic_cuda_deduce_arithmetic = _If< + _CCCL_TRAIT(is_floating_point, _Type), + _If, + __atomic_cuda_operand_deduction>, + _If<_CCCL_TRAIT(is_signed, _Type), + __type_switch>, + __type_case<2, __atomic_cuda_operand_deduction>, + __type_case<4, __atomic_cuda_operand_deduction>, + __type_default<__atomic_cuda_operand_deduction>>, // There is no + // atom.add.s64 + __type_switch>, + __type_case<2, __atomic_cuda_operand_deduction>, + __type_case<4, __atomic_cuda_operand_deduction>, + __type_default<__atomic_cuda_operand_deduction>>>>; template -using __atomic_cuda_deduce_minmax = - _If<_CCCL_TRAIT(is_floating_point, _Type), - _If, - __atomic_cuda_operand_deduction>, - _If<_CCCL_TRAIT(is_signed, _Type), - _If, - _If, - _If, - __atomic_cuda_operand_deduction>>>, // atom.min|max.s64 - // supported - _If, - _If, - _If, - __atomic_cuda_operand_deduction>>>>>; +using __atomic_cuda_deduce_minmax = _If< + _CCCL_TRAIT(is_floating_point, _Type), + _If, + __atomic_cuda_operand_deduction>, + _If<_CCCL_TRAIT(is_signed, _Type), + __type_switch>, + __type_case<2, __atomic_cuda_operand_deduction>, + __type_case<4, __atomic_cuda_operand_deduction>, + __type_default<__atomic_cuda_operand_deduction>>, // atom.min|max.s64 + // supported + __type_switch>, + __type_case<2, __atomic_cuda_operand_deduction>, + __type_case<4, __atomic_cuda_operand_deduction>, + __type_default<__atomic_cuda_operand_deduction>>>>; template using __atomic_enable_if_native_bitwise = bool; diff --git a/libcudacxx/include/cuda/std/__cccl/dialect.h b/libcudacxx/include/cuda/std/__cccl/dialect.h index 407f2db6ecf..06387172b9b 100644 --- a/libcudacxx/include/cuda/std/__cccl/dialect.h +++ b/libcudacxx/include/cuda/std/__cccl/dialect.h @@ -105,6 +105,15 @@ # define _CCCL_NO_VARIABLE_TEMPLATES #endif // _CCCL_STD_VER <= 2011 +// Declaring a non-type template parameters with auto is only available from C++17 onwards +#if _CCCL_STD_VER >= 2017 && defined(__cpp_nontype_template_parameter_auto) \ + && (__cpp_nontype_template_parameter_auto >= 201606L) +# define _CCCL_NTTP_AUTO auto +#else // ^^^ C++17 ^^^ / vvv C++14 vvv +# define _CCCL_NO_NONTYPE_TEMPLATE_PARAMETER_AUTO +# define _CCCL_NTTP_AUTO unsigned long long int +#endif // _CCCL_STD_VER <= 2014 + // concepts are only available from C++20 onwards #if _CCCL_STD_VER <= 2017 || !defined(__cpp_concepts) || (__cpp_concepts < 201907L) # define _CCCL_NO_CONCEPTS diff --git a/libcudacxx/include/cuda/std/__type_traits/type_list.h b/libcudacxx/include/cuda/std/__type_traits/type_list.h index 00f69273673..1beb22b1807 100644 --- a/libcudacxx/include/cuda/std/__type_traits/type_list.h +++ b/libcudacxx/include/cuda/std/__type_traits/type_list.h @@ -557,6 +557,100 @@ using __type_front = __type_at_c<0, _List>; template using __type_back = __type_at_c<_List::__size - 1, _List>; +//! \brief A pair of types +template +struct _CCCL_TYPE_VISIBILITY_DEFAULT __type_pair +{ + using __first _CCCL_NODEBUG_ALIAS = _First; + using __second _CCCL_NODEBUG_ALIAS = _Second; +}; + +//! \brief Retrieve the first of a pair of types +//! \pre \c _Pair is a specialization of \c __type_pair +template +using __type_pair_first _CCCL_NODEBUG_ALIAS = typename _Pair::__first; + +//! \brief Retrieve the second of a pair of types +//! \pre \c _Pair is a specialization of \c __type_pair +template +using __type_pair_second _CCCL_NODEBUG_ALIAS = typename _Pair::__second; + +//! \see __type_switch +template +struct _CCCL_TYPE_VISIBILITY_DEFAULT __type_default +{ + template + using __rebind _CCCL_NODEBUG_ALIAS = __type_default; + + using type _CCCL_NODEBUG_ALIAS = _Value; +}; + +# if _CCCL_CUDACC_AT_LEAST(12, 0) || defined(_CCCL_DOXYGEN_INVOKED) + +//! \see __type_switch +template <_CCCL_NTTP_AUTO _Label, class _Value> +struct _CCCL_TYPE_VISIBILITY_DEFAULT __type_case +{ + template + using __rebind _CCCL_NODEBUG_ALIAS = __type_case(_Label), _Value>; + + using type = _Value; +}; + +# else // ^^^ CUDACC >= 12.0 || DOXYGEN ^^^ / vvv CUDACC < 12.0 && !DOXYGEN vvv + +template +struct _CCCL_TYPE_VISIBILITY_DEFAULT __type_case_ +{ + template + using __rebind _CCCL_NODEBUG_ALIAS = __type_case_, _Value>; + + using type = _Value; +}; + +template <_CCCL_NTTP_AUTO _Label, class _Value> +using __type_case _CCCL_NODEBUG_ALIAS = __type_case_, _Value>; + +# endif // CUDACC < 12.0 && !DOXYGEN + +namespace __detail +{ +template <_CCCL_NTTP_AUTO _Label, class _Value> +_LIBCUDACXX_HIDE_FROM_ABI auto __type_switch_fn(__type_case<_Label, _Value>*, int) -> __type_case<_Label, _Value>; + +template <_CCCL_NTTP_AUTO _Label, class _Value> +_LIBCUDACXX_HIDE_FROM_ABI auto __type_switch_fn(__type_default<_Value>*, long) -> __type_default<_Value>; +} // namespace __detail + +//! \see __type_switch +template +struct _CCCL_TYPE_VISIBILITY_DEFAULT _LIBCUDACXX_DECLSPEC_EMPTY_BASES __type_switch_fn + : _Cases::template __rebind<_Type>... +{ + template + using __call _CCCL_NODEBUG_ALIAS = + __type(static_cast<__type_switch_fn*>(nullptr), 0))>; +}; + +//! \brief Given an integral constant \c _Label and a pack of "cases" +//! consisting of one or more specializations of \c __type_case and zero or +//! one specializations of \c __type_default, `__type_switch<_Label, _Cases...>` +//! returns the value associated with the first case whose label matches the +//! given label. If no such case exists, the value associated with the default +//! case is returned. If no default case exists, the type is ill-formed. +//! +//! \p Example: +//! \code +//! using result = __type_switch<2, +//! __type_case<1, char>, +//! __type_case<2, double>, +//! __type_default>; +//! static_assert(is_same_v); +//! \endcode +template <_CCCL_NTTP_AUTO _Label, class... _Cases> +using __type_switch _CCCL_NODEBUG_ALIAS = + __type_call<__type_switch_fn, integral_constant>; + namespace __detail { # if _CCCL_COMPILER(MSVC, <, 19, 38) @@ -907,24 +1001,6 @@ struct _CCCL_TYPE_VISIBILITY_DEFAULT __type_sizeof using __call _CCCL_NODEBUG_ALIAS = integral_constant; }; -//! \brief A pair of types -template -struct _CCCL_TYPE_VISIBILITY_DEFAULT __type_pair -{ - using __first _CCCL_NODEBUG_ALIAS = _First; - using __second _CCCL_NODEBUG_ALIAS = _Second; -}; - -//! \brief Retreive the first of a pair of types -//! \pre \c _Pair is a specialization of \c __type_pair -template -using __type_pair_first = typename _Pair::__first; - -//! \brief Retreive the second of a pair of types -//! \pre \c _Pair is a specialization of \c __type_pair -template -using __type_pair_second = typename _Pair::__second; - //! \brief A list of compile-time values, and a meta-callable that accepts a //! meta-callable and evaluates it with the values, each value wrapped in an //! integral constant wrapper. diff --git a/libcudacxx/test/libcudacxx/cuda/type_list.pass.cpp b/libcudacxx/test/libcudacxx/cuda/type_list.pass.cpp index 2e477d3622a..9978d7e2c35 100644 --- a/libcudacxx/test/libcudacxx/cuda/type_list.pass.cpp +++ b/libcudacxx/test/libcudacxx/cuda/type_list.pass.cpp @@ -494,6 +494,26 @@ static_assert( ""); #endif +// __type_switch +static_assert(::cuda::std::is_same<::cuda::std::__type_switch<0, + ::cuda::std::__type_case<0, char>, + ::cuda::std::__type_case<1, double>, + ::cuda::std::__type_default>, + char>::value, + ""); +static_assert(::cuda::std::is_same<::cuda::std::__type_switch<1, + ::cuda::std::__type_case<0, char>, + ::cuda::std::__type_case<1, double>, + ::cuda::std::__type_default>, + double>::value, + ""); +static_assert(::cuda::std::is_same<::cuda::std::__type_switch<2, + ::cuda::std::__type_case<0, char>, + ::cuda::std::__type_case<1, double>, + ::cuda::std::__type_default>, + float>::value, + ""); + // __type_concat static_assert(::cuda::std::is_same<::cuda::std::__type_concat<>, ::cuda::std::__type_list<>>::value, "");