From de2b633a4a06c267d3361dd3c8a4d097156a18f8 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sun, 23 Jun 2019 03:58:41 +0000 Subject: [PATCH] Add super fast _IsSame trait for internal use. Clang provides __is_same that doesn't produce any instantiations and just returns a bool. It's a lot faster than using std::is_same I'll follow up with a patch to actually start using it. llvm-svn: 364148 --- libcxx/include/type_traits | 31 ++++++---- .../stress_tests/stress_test_is_same.sh.cpp | 57 +++++++++++++++++++ 2 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_is_same.sh.cpp diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index 05405c96e56b..def01d459cbf 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -542,6 +542,26 @@ template struct _LIBCPP_TEMPLATE_VIS enable_if {typedef _ template using enable_if_t = typename enable_if<_Bp, _Tp>::type; #endif +// is_same + +template struct _LIBCPP_TEMPLATE_VIS is_same : public false_type {}; +template struct _LIBCPP_TEMPLATE_VIS is_same<_Tp, _Tp> : public true_type {}; + +#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) +template +_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_same_v + = is_same<_Tp, _Up>::value; +#endif + +template +using _IsSame = _BoolConstant< +#ifdef __clang__ + __is_same(_Tp, _Up) +#else + _VSTD::is_same<_Tp, _Up>::value +#endif +>; + // addressof #ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF @@ -933,17 +953,6 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_class_v = is_class<_Tp>::value; #endif -// is_same - -template struct _LIBCPP_TEMPLATE_VIS is_same : public false_type {}; -template struct _LIBCPP_TEMPLATE_VIS is_same<_Tp, _Tp> : public true_type {}; - -#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) -template -_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_same_v - = is_same<_Tp, _Up>::value; -#endif - // is_function namespace __libcpp_is_function_imp diff --git a/libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_is_same.sh.cpp b/libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_is_same.sh.cpp new file mode 100644 index 000000000000..8e3f0d1b2dc2 --- /dev/null +++ b/libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_is_same.sh.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is a dummy feature that prevents this test from running by default. + + +// The table below compares the compile time and object size for each of the +// variants listed in the RUN script. +// +// Impl Compile Time Object Size +// ------------------------------------------- +// std::_IsSame: 689.634 ms 356 K +// std::is_same: 8,129.180 ms 560 K +// +// RUN: %cxx %flags %compile_flags -c %s -o %S/orig.o -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 +// RUN: %cxx %flags %compile_flags -c %s -o %S/new.o -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 -DTEST_NEW + +#include +#include + +#include "test_macros.h" +#include "template_cost_testing.h" + +template struct Arg { enum { value = 1 }; }; + +#ifdef TEST_NEW +#define IS_SAME std::_IsSame +#else +#define IS_SAME std::is_same +#endif + +#define TEST_CASE_NOP() IS_SAME < Arg< __COUNTER__ >, Arg < __COUNTER__ > >::value, +#define TEST_CASE_TYPE() IS_SAME < Arg< __COUNTER__ >, Arg < __COUNTER__ > >, + +int sink(...); + +int x = sink( + REPEAT_10000(TEST_CASE_NOP) + REPEAT_10000(TEST_CASE_NOP) 42 +); + +void Foo( REPEAT_1000(TEST_CASE_TYPE) int) { } + +static_assert(__COUNTER__ > 10000, ""); + +void escape() { + +sink(&x); +sink(&Foo); +} + +