Commit 732eb076 by François Dumont

c++config (_GLIBCXX14_USE_CONSTEXPR): New.

2016-05-24  François Dumont  <fdumont@gcc.gnu.org>

	* include/bits/c++config (_GLIBCXX14_USE_CONSTEXPR): New.
	* include/bits/hashtable_policy.h
	(_Prime_rehash_policy::__has_load_factor): New. Mark rehash policy
	having load factor management.
	(_Mask_range_hashing): New.
	(__clp2): New.
	(_Power2_rehash_policy): New.
	(_Inserts<>): Remove last template parameter, _Unique_keys, so that
	partial specializations only depend on whether iterators are constant
	or not.
	* testsuite/23_containers/unordered_set/hash_policy/26132.cc: Adapt to
	test new hash policy.
	* testsuite/23_containers/unordered_set/hash_policy/load_factor.cc:
	Likewise.
	* testsuite/23_containers/unordered_set/hash_policy/rehash.cc:
	Likewise.
	* testsuite/23_containers/unordered_set/insert/hash_policy.cc:
	Likewise.
	* testsuite/23_containers/unordered_set/max_load_factor/robustness.cc:
	Likewise.
	* testsuite/23_containers/unordered_set/hash_policy/power2_rehash.cc:
	New.
	* testsuite/performance/23_containers/insert/54075.cc: Add benchmark
	using the new hash policy.
	* testsuite/performance/23_containers/insert_erase/41975.cc: Likewise.

From-SVN: r236669
parent f65e97fd
2016-05-24 François Dumont <fdumont@gcc.gnu.org>
* include/bits/c++config (_GLIBCXX14_USE_CONSTEXPR): New.
* include/bits/hashtable_policy.h
(_Prime_rehash_policy::__has_load_factor): New. Mark rehash policy
having load factor management.
(_Mask_range_hashing): New.
(__clp2): New.
(_Power2_rehash_policy): New.
(_Inserts<>): Remove last template parameter, _Unique_keys, so that
partial specializations only depend on whether iterators are constant
or not.
* testsuite/23_containers/unordered_set/hash_policy/26132.cc: Adapt to
test new hash policy.
* testsuite/23_containers/unordered_set/hash_policy/load_factor.cc:
Likewise.
* testsuite/23_containers/unordered_set/hash_policy/rehash.cc:
Likewise.
* testsuite/23_containers/unordered_set/insert/hash_policy.cc:
Likewise.
* testsuite/23_containers/unordered_set/max_load_factor/robustness.cc:
Likewise.
* testsuite/23_containers/unordered_set/hash_policy/power2_rehash.cc:
New.
* testsuite/performance/23_containers/insert/54075.cc: Add benchmark
using the new hash policy.
* testsuite/performance/23_containers/insert_erase/41975.cc: Likewise.
2016-05-24 Jonathan Wakely <jwakely@redhat.com> 2016-05-24 Jonathan Wakely <jwakely@redhat.com>
* include/bits/stl_queue.h (priority_queue::value_compare): Define. * include/bits/stl_queue.h (priority_queue::value_compare): Define.
......
...@@ -106,8 +106,10 @@ ...@@ -106,8 +106,10 @@
#ifndef _GLIBCXX14_CONSTEXPR #ifndef _GLIBCXX14_CONSTEXPR
# if __cplusplus >= 201402L # if __cplusplus >= 201402L
# define _GLIBCXX14_CONSTEXPR constexpr # define _GLIBCXX14_CONSTEXPR constexpr
# define _GLIBCXX14_USE_CONSTEXPR constexpr
# else # else
# define _GLIBCXX14_CONSTEXPR # define _GLIBCXX14_CONSTEXPR
# define _GLIBCXX14_USE_CONSTEXPR const
# endif # endif
#endif #endif
......
...@@ -23,15 +23,16 @@ ...@@ -23,15 +23,16 @@
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
// libstdc++/26132 // libstdc++/26132
void test01() template<typename _USet>
{ void test()
{
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
for (float lf = 1.0; lf < 101.0; lf *= 10.0) for (float lf = 1.0; lf < 101.0; lf *= 10.0)
for (int size = 1; size <= 6561; size *= 3) for (int size = 1; size <= 6561; size *= 3)
{ {
std::unordered_set<int> us1; _USet us1;
typedef std::unordered_set<int>::size_type size_type; typedef typename _USet::size_type size_type;
us1.max_load_factor(10.0); us1.max_load_factor(10.0);
...@@ -48,10 +49,22 @@ void test01() ...@@ -48,10 +49,22 @@ void test01()
VERIFY( us1.bucket_count() >= n ); VERIFY( us1.bucket_count() >= n );
} }
} }
} }
template<typename _Value>
using unordered_set_power2_rehash =
std::_Hashtable<_Value, _Value, std::allocator<_Value>,
std::__detail::_Identity,
std::equal_to<_Value>,
std::hash<_Value>,
std::__detail::_Mask_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Power2_rehash_policy,
std::__detail::_Hashtable_traits<false, true, true>>;
int main() int main()
{ {
test01(); test<std::unordered_set<int>>();
test<unordered_set_power2_rehash<int>>();
return 0; return 0;
} }
...@@ -18,13 +18,15 @@ ...@@ -18,13 +18,15 @@
// { dg-options "-std=gnu++11" } // { dg-options "-std=gnu++11" }
#include <unordered_set> #include <unordered_set>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
void test01() template<typename _USet>
{ void test()
{
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
{ {
std::unordered_set<int> us; _USet us;
for (int i = 0; i != 100000; ++i) for (int i = 0; i != 100000; ++i)
{ {
us.insert(i); us.insert(i);
...@@ -32,7 +34,7 @@ void test01() ...@@ -32,7 +34,7 @@ void test01()
} }
} }
{ {
std::unordered_set<int> us; _USet us;
us.max_load_factor(3.f); us.max_load_factor(3.f);
for (int i = 0; i != 100000; ++i) for (int i = 0; i != 100000; ++i)
{ {
...@@ -41,7 +43,7 @@ void test01() ...@@ -41,7 +43,7 @@ void test01()
} }
} }
{ {
std::unordered_set<int> us; _USet us;
us.max_load_factor(.3f); us.max_load_factor(.3f);
for (int i = 0; i != 100000; ++i) for (int i = 0; i != 100000; ++i)
{ {
...@@ -49,10 +51,22 @@ void test01() ...@@ -49,10 +51,22 @@ void test01()
VERIFY( us.load_factor() <= us.max_load_factor() ); VERIFY( us.load_factor() <= us.max_load_factor() );
} }
} }
} }
template<typename _Value>
using unordered_set_power2_rehash =
std::_Hashtable<_Value, _Value, std::allocator<_Value>,
std::__detail::_Identity,
std::equal_to<_Value>,
std::hash<_Value>,
std::__detail::_Mask_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Power2_rehash_policy,
std::__detail::_Hashtable_traits<false, true, true>>;
int main() int main()
{ {
test01(); test<std::unordered_set<int>>();
test<unordered_set_power2_rehash<int>>();
return 0; return 0;
} }
// Copyright (C) 2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
//
// { dg-options "-std=gnu++11" }
#include <unordered_set>
#include <testsuite_hooks.h>
void test01()
{
bool test __attribute__((unused)) = true;
std::__detail::_Power2_rehash_policy policy;
VERIFY( policy._M_next_bkt(1) == 2 );
VERIFY( policy._M_next_bkt(2) == 4 );
VERIFY( policy._M_next_bkt(3) == 4 );
VERIFY( policy._M_next_bkt(5) == 8 );
VERIFY( policy._M_next_bkt(33) == 64 );
VERIFY( policy._M_next_bkt((std::size_t(1) << (sizeof(std::size_t) * 8 - 2)) + 1)
== (std::size_t(1) << (sizeof(std::size_t) * 8 - 1)) );
}
int main()
{
test01();
return 0;
}
...@@ -18,13 +18,15 @@ ...@@ -18,13 +18,15 @@
// { dg-options "-std=gnu++11" } // { dg-options "-std=gnu++11" }
#include <unordered_set> #include <unordered_set>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
void test01() template<typename _USet>
void test()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
std::unordered_set<int> us; _USet us;
typedef typename std::unordered_set<int>::size_type size_type; typedef typename _USet::size_type size_type;
bool rehashed = false; bool rehashed = false;
for (int i = 0; i != 100000; ++i) for (int i = 0; i != 100000; ++i)
{ {
...@@ -55,8 +57,20 @@ void test01() ...@@ -55,8 +57,20 @@ void test01()
VERIFY( rehashed ); VERIFY( rehashed );
} }
template<typename _Value>
using unordered_set_power2_rehash =
std::_Hashtable<_Value, _Value, std::allocator<_Value>,
std::__detail::_Identity,
std::equal_to<_Value>,
std::hash<_Value>,
std::__detail::_Mask_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Power2_rehash_policy,
std::__detail::_Hashtable_traits<false, true, true>>;
int main() int main()
{ {
test01(); test<std::unordered_set<int>>();
test<unordered_set_power2_rehash<int>>();
return 0; return 0;
} }
...@@ -20,15 +20,23 @@ ...@@ -20,15 +20,23 @@
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
#include <limits> #include <limits>
#include <ext/throw_allocator.h> #include <ext/throw_allocator.h>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
void test01() template<template<typename _Value, typename _Hash,
{ typename _Pred, typename _Alloc>
typename _USet>
void test01()
{
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
// Make sure whatever happen we restore throw allocator limit at exit.
__gnu_cxx::limit_condition::adjustor_base adj;
typedef std::numeric_limits<std::size_t> nl_size_t; typedef std::numeric_limits<std::size_t> nl_size_t;
std::unordered_set<int, std::hash<int>, std::equal_to<int>, _USet<int, std::hash<int>, std::equal_to<int>,
__gnu_cxx::throw_allocator_limit<int> > us; __gnu_cxx::throw_allocator_limit<int> > us;
const int nb = 100; const int nb = 100;
int scheduled_throw_counter = 0; int scheduled_throw_counter = 0;
...@@ -61,14 +69,20 @@ void test01() ...@@ -61,14 +69,20 @@ void test01()
{ {
VERIFY( us.count(i) == 1 ); VERIFY( us.count(i) == 1 );
} }
} }
void test02() template<template<typename _Value, typename _Hash,
{ typename _Pred, typename _Alloc>
typename _USet>
void test02()
{
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
// Make sure whatever happen we restore throw allocator limit at exit.
__gnu_cxx::limit_condition::adjustor_base adj;
typedef std::numeric_limits<std::size_t> nl_size_t; typedef std::numeric_limits<std::size_t> nl_size_t;
std::unordered_set<int, std::hash<int>, std::equal_to<int>, _USet<int, std::hash<int>, std::equal_to<int>,
__gnu_cxx::throw_allocator_limit<int> > us; __gnu_cxx::throw_allocator_limit<int> > us;
const int nb = 100; const int nb = 100;
int scheduled_throw_counter = 0; int scheduled_throw_counter = 0;
...@@ -103,11 +117,25 @@ void test02() ...@@ -103,11 +117,25 @@ void test02()
{ {
VERIFY( us.count(i) == 1 ); VERIFY( us.count(i) == 1 );
} }
} }
template<typename _Value, typename _Hash,
typename _Pred, typename _Alloc>
using unordered_set_power2_rehash =
std::_Hashtable<_Value, _Value, _Alloc,
std::__detail::_Identity,
_Pred,
_Hash,
std::__detail::_Mask_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Power2_rehash_policy,
std::__detail::_Hashtable_traits<false, true, true>>;
int main() int main()
{ {
test01(); test01<std::unordered_set>();
test02(); test01<unordered_set_power2_rehash>();
test02<std::unordered_set>();
test02<unordered_set_power2_rehash>();
return 0; return 0;
} }
...@@ -22,12 +22,15 @@ ...@@ -22,12 +22,15 @@
#include <ext/throw_allocator.h> #include <ext/throw_allocator.h>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
void test01() template<template<typename _Value, typename _Hash,
{ typename _Pred, typename _Alloc>
typename _USet>
void test()
{
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef std::numeric_limits<std::size_t> nl_size_t; typedef std::numeric_limits<std::size_t> nl_size_t;
std::unordered_set<int, std::hash<int>, std::equal_to<int>, _USet<int, std::hash<int>, std::equal_to<int>,
__gnu_cxx::throw_allocator_limit<int> > us; __gnu_cxx::throw_allocator_limit<int> > us;
int val = 0; int val = 0;
for (; val != 100; ++val) for (; val != 100; ++val)
...@@ -41,7 +44,7 @@ void test01() ...@@ -41,7 +44,7 @@ void test01()
std::size_t thrown_exceptions = 0; std::size_t thrown_exceptions = 0;
// Reduce max load factor. // Reduce max load factor.
us.max_load_factor(us.max_load_factor() / 2); us.max_load_factor(us.max_load_factor() / 4);
// At this point load factor is higher than max_load_factor because we can't // At this point load factor is higher than max_load_factor because we can't
// rehash in max_load_factor call. // rehash in max_load_factor call.
...@@ -49,7 +52,7 @@ void test01() ...@@ -49,7 +52,7 @@ void test01()
while (true) while (true)
{ {
__gnu_cxx::limit_condition::set_limit(counter++); __gnu_cxx::limit_condition::limit_adjustor adjustor(counter++);
bool do_break = false; bool do_break = false;
try try
{ {
...@@ -57,7 +60,6 @@ void test01() ...@@ -57,7 +60,6 @@ void test01()
// Check that unordered_set will still be correctly resized when // Check that unordered_set will still be correctly resized when
// needed. // needed.
VERIFY( us.insert(val++).second ); VERIFY( us.insert(val++).second );
VERIFY( us.bucket_count() != nbkts ); VERIFY( us.bucket_count() != nbkts );
VERIFY( us.load_factor() <= us.max_load_factor() ); VERIFY( us.load_factor() <= us.max_load_factor() );
do_break = true; do_break = true;
...@@ -65,7 +67,7 @@ void test01() ...@@ -65,7 +67,7 @@ void test01()
catch (const __gnu_cxx::forced_error&) catch (const __gnu_cxx::forced_error&)
{ {
// max load factor doesn't change. // max load factor doesn't change.
VERIFY( us.max_load_factor() == .5f ); VERIFY( us.max_load_factor() == .25f );
++thrown_exceptions; ++thrown_exceptions;
} }
...@@ -74,10 +76,24 @@ void test01() ...@@ -74,10 +76,24 @@ void test01()
} }
VERIFY( thrown_exceptions > 0 ); VERIFY( thrown_exceptions > 0 );
} }
template<typename _Value, typename _Hash,
typename _Pred, typename _Alloc>
using unordered_set_power2_rehash =
std::_Hashtable<_Value, _Value, _Alloc,
std::__detail::_Identity,
_Pred,
_Hash,
std::__detail::_Mask_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Power2_rehash_policy,
std::__detail::_Hashtable_traits<false, true, true>>;
int main() int main()
{ {
test01(); test<std::unordered_set>();
test<unordered_set_power2_rehash>();
return 0; return 0;
} }
...@@ -127,8 +127,28 @@ template<bool cache> ...@@ -127,8 +127,28 @@ template<bool cache>
using __umset = std::__umset_hashtable<Foo, HashFunction, using __umset = std::__umset_hashtable<Foo, HashFunction,
std::equal_to<Foo>, std::equal_to<Foo>,
std::allocator<Foo>, std::allocator<Foo>,
std::__umset_traits<cache>>;
template<bool cache>
using __uset2 =
std::_Hashtable<Foo, Foo, std::allocator<Foo>,
std::__detail::_Identity,
std::equal_to<Foo>, HashFunction,
std::__detail::_Mask_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Power2_rehash_policy,
std::__uset_traits<cache>>; std::__uset_traits<cache>>;
template<bool cache>
using __umset2 =
std::_Hashtable<Foo, Foo, std::allocator<Foo>,
std::__detail::_Identity,
std::equal_to<Foo>, HashFunction,
std::__detail::_Mask_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Power2_rehash_policy,
std::__umset_traits<cache>>;
int main() int main()
{ {
using namespace __gnu_test; using namespace __gnu_test;
...@@ -181,6 +201,19 @@ int main() ...@@ -181,6 +201,19 @@ int main()
stop_counters(time, resource); stop_counters(time, resource);
report_performance(__FILE__, "std benches", time, resource); report_performance(__FILE__, "std benches", time, resource);
start_counters(time, resource);
bench<__uset2<false>>(
"std::unordered_set2 without hash code cached ", foos);
bench<__uset2<true>>(
"std::unordered_set2 with hash code cached ", foos);
bench<__umset2<false>>(
"std::unordered_multiset2 without hash code cached ", foos);
bench<__umset2<true>>(
"std::unordered_multiset2 with hash code cached ", foos);
stop_counters(time, resource);
report_performance(__FILE__, "std2 benches", time, resource);
bench<std::unordered_set<Foo, HashFunction>>( bench<std::unordered_set<Foo, HashFunction>>(
"std::unordered_set default cache ", foos); "std::unordered_set default cache ", foos);
bench<std::unordered_multiset<Foo, HashFunction>>( bench<std::unordered_multiset<Foo, HashFunction>>(
......
...@@ -177,6 +177,16 @@ template<bool cache> ...@@ -177,6 +177,16 @@ template<bool cache>
cache>; cache>;
template<bool cache> template<bool cache>
using __uset2 =
std::_Hashtable<int, int, std::allocator<int>,
std::__detail::_Identity,
std::equal_to<int>, std::hash<int>,
std::__detail::_Mask_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Power2_rehash_policy,
std::__uset_traits<cache>>;
template<bool cache>
using __str_uset = using __str_uset =
std::__uset_hashtable<std::string, std::hash<std::string>, std::__uset_hashtable<std::string, std::hash<std::string>,
std::equal_to<std::string>, std::equal_to<std::string>,
...@@ -190,6 +200,16 @@ template<bool cache> ...@@ -190,6 +200,16 @@ template<bool cache>
std::allocator<std::string>, std::allocator<std::string>,
cache>; cache>;
template<bool cache>
using __str_uset2 =
std::_Hashtable<std::string, std::string, std::allocator<std::string>,
std::__detail::_Identity,
std::equal_to<std::string>, std::hash<std::string>,
std::__detail::_Mask_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Power2_rehash_policy,
std::__uset_traits<cache>>;
int main() int main()
{ {
bench<__tr1_uset<false>>( bench<__tr1_uset<false>>(
...@@ -202,6 +222,10 @@ int main() ...@@ -202,6 +222,10 @@ int main()
"std::unordered_set<int> with hash code cached"); "std::unordered_set<int> with hash code cached");
bench<std::unordered_set<int>>( bench<std::unordered_set<int>>(
"std::unordered_set<int> default cache"); "std::unordered_set<int> default cache");
bench<__uset2<false>>(
"std::unordered_set2<int> without hash code cached");
bench<__uset2<true>>(
"std::unordered_set2<int> with hash code cached");
bench_str<__tr1_str_uset<false>>( bench_str<__tr1_str_uset<false>>(
"std::tr1::unordered_set<string> without hash code cached"); "std::tr1::unordered_set<string> without hash code cached");
bench_str<__tr1_str_uset<true>>( bench_str<__tr1_str_uset<true>>(
...@@ -212,5 +236,9 @@ int main() ...@@ -212,5 +236,9 @@ int main()
"std::unordered_set<string> with hash code cached"); "std::unordered_set<string> with hash code cached");
bench_str<std::unordered_set<std::string>>( bench_str<std::unordered_set<std::string>>(
"std::unordered_set<string> default cache"); "std::unordered_set<string> default cache");
bench_str<__str_uset2<false>>(
"std::unordered_set2<string> without hash code cached");
bench_str<__str_uset2<true>>(
"std::unordered_set2<string> with hash code cached");
return 0; return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment