From b3be1a206b3a139b75e22478374088f485ca7a1c Mon Sep 17 00:00:00 2001 From: Tom Scogland Date: Mon, 29 Jun 2020 11:09:49 -0700 Subject: [PATCH] use integer_pack, make_integer_seq and type_pack_e We were already using __make_integer_seq, incorporate the __integer_pack code from the concepts refactor branch and add cases for intel, nvcc and pgi to be able to use one or more of these intrinsics as well. It turns out EDG supports __make_integer_seq and __integer_pack, but only when configured some certain way. NVCC supports both, with the clang builtin supported only when clang is selected as a host compiler and __integer_pack supported only in version 10+ and only with a g++ >= 8 selected as host compiler. Both of PGI and Intel seem to do something similar, supporting only __integer_pack, and only when their targeted compiler and libstdc++ is 8+. I have yet to try XL, but that's next. --- include/camp/defines.hpp | 33 +++++++++++++++++++++++++++++++-- include/camp/list/at.hpp | 12 ++++++++++-- include/camp/number.hpp | 7 ++++++- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/include/camp/defines.hpp b/include/camp/defines.hpp index c37e3bc..dea5d69 100644 --- a/include/camp/defines.hpp +++ b/include/camp/defines.hpp @@ -98,10 +98,39 @@ namespace camp #define CAMP_HAVE_OMP_OFFLOAD 1 #endif -#if defined(__has_builtin) -#if __has_builtin(__make_integer_seq) +// This works for clang, nvcc 10 and higher using clang as a host compiler +#define CAMP_USE_MAKE_INTEGER_SEQ 0 +#define CAMP_USE_TYPE_PACK_ELEMENT 0 +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191125507 + // __has_builtin exists but does not always expose this +#undef CAMP_USE_MAKE_INTEGER_SEQ #define CAMP_USE_MAKE_INTEGER_SEQ 1 +#undef CAMP_USE_TYPE_PACK_ELEMENT +#define CAMP_USE_TYPE_PACK_ELEMENT 1 +#elif defined(__has_builtin) +#if __has_builtin(__make_integer_seq) && ((!defined(__NVCC__) || __CUDACC_VER_MAJOR >= 10)) +#undef CAMP_USE_MAKE_INTEGER_SEQ +#define CAMP_USE_MAKE_INTEGER_SEQ 1 +#undef CAMP_USE_TYPE_PACK_ELEMENT +#define CAMP_USE_TYPE_PACK_ELEMENT 1 +#endif #endif + +// This works for: +// GCC >= 8 +// intel 19+ in GCC 8 or higher mode +// nvcc 10+ in GCC 8 or higher mode +// PGI 19+ in GCC 8 or higher mode +#if __GNUC__ >= 8 && (\ + /* intel compiler in gcc 8+ mode */ \ + ((!defined(__INTEL_COMPILER)) || __INTEL_COMPILER >= 1900) \ + /* nvcc in gcc 8+ mode */ \ + ||((!defined(__NVCC__)) || __CUDACC_VER_MAJOR >= 10) \ + ||((!defined(__PGIC__)) || __PGIC__ >= 19) \ + ) +#define CAMP_USE_INTEGER_PACK 1 +#else +#define CAMP_USE_INTEGER_PACK 0 #endif // libstdc++ from GCC below version 5 lacks the type trait diff --git a/include/camp/list/at.hpp b/include/camp/list/at.hpp index 83aaf34..8374f3d 100644 --- a/include/camp/list/at.hpp +++ b/include/camp/list/at.hpp @@ -22,6 +22,15 @@ namespace camp namespace detail { + template + struct _at; + + #if CAMP_USE_TYPE_PACK_ELEMENT + template class T, typename... Pack> + struct _at, Idx> { + using type = __type_pack_element; + }; + #else // Lookup from metal::at machinery template struct entry { @@ -45,8 +54,6 @@ namespace detail : decltype(_lookup_impl(declptr>())) { }; - template - struct _at; template