Index: configure.host =================================================================== --- configure.host (revision 191092) +++ configure.host (working copy) @@ -50,6 +50,8 @@ # cpu_defines_dir location of cpu_defines.h # defaults to generic. # +# cpu_opt_ext_random path name of random.h containing CPU-specific +# optimizations # # error_constants_dir location of error_constants.h # defaults to os/generic. @@ -183,6 +185,18 @@ fi +# Set directory with CPU-specific optimization +cpu_opt_dir=${cpu_include_dir}/opt +test -d ${glibcxx_srcdir}/config/${cpu_include_dir}/opt || +cpu_opt_dir=cpu/generic/opt +# For each header with CPU-specific optimizations check whether it +# exists in ${cpu_opt_dir}. If not, point the variable at the +# appropriate file in the generic directory. +cpu_opt_ext_random=${cpu_opt_dir}/ext/opt_random.h +test -f ${glibcxx_srcdir}/config/${cpu_opt_ext_random} || +cpu_opt_ext_random=cpu/generic/opt/ext/opt_random.h + + # Set any OS-dependent bits. # Set the os_include_dir. # Set the error_costants_dir. Index: configure.ac =================================================================== --- configure.ac (revision 191092) +++ configure.ac (working copy) @@ -390,6 +390,7 @@ OS_INC_SRCDIR=config/${os_include_dir} ERROR_CONSTANTS_SRCDIR=config/${error_constants_dir} ABI_TWEAKS_SRCDIR=config/${abi_tweaks_dir} +CPU_OPT_EXT_RANDOM=config/${cpu_opt_ext_random} AC_SUBST(ATOMICITY_SRCDIR) AC_SUBST(ATOMIC_WORD_SRCDIR) AC_SUBST(ATOMIC_FLAGS) @@ -397,6 +398,7 @@ AC_SUBST(ABI_TWEAKS_SRCDIR) AC_SUBST(OS_INC_SRCDIR) AC_SUBST(ERROR_CONSTANTS_SRCDIR) +AC_SUBST(CPU_OPT_EXT_RANDOM) # Determine cross-compile flags and AM_CONDITIONALs. Index: include/Makefile.am =================================================================== --- include/Makefile.am (revision 191092) +++ include/Makefile.am (working copy) @@ -533,12 +533,16 @@ ${ext_srcdir}/vstring.tcc \ ${ext_srcdir}/vstring_fwd.h \ ${ext_srcdir}/vstring_util.h \ - ${ext_compat_headers} + ${ext_compat_headers} \ + ${ext_host_headers} ext_compat_headers = \ ${backward_srcdir}/hash_set \ ${backward_srcdir}/hash_map +ext_host_headers = \ + ${glibcxx_srcdir}/${CPU_OPT_EXT_RANDOM} + tr1_srcdir = ${glibcxx_srcdir}/include/tr1 tr1_builddir = ./tr1 tr1_headers = \ Index: include/ext/random =================================================================== --- include/ext/random (revision 191092) +++ include/ext/random (working copy) @@ -120,24 +120,22 @@ return _M_stateT[_M_pos++]; } -#ifdef __SSE2__ - friend bool - operator==(const simd_fast_mersenne_twister_engine& __lhs, - const simd_fast_mersenne_twister_engine& __rhs) - { __m128i __res = _mm_cmpeq_epi8(__lhs._M_state[0], __rhs._M_state[0]); - for (size_t __i = 1; __i < __lhs._M_nstate; ++__i) - __res = _mm_and_si128(__res, _mm_cmpeq_epi8(__lhs._M_state[__i], - __rhs._M_state[__i])); - return (_mm_movemask_epi8(__res) == 0xffff - && __lhs._M_pos == __rhs._M_pos); } -#else - friend bool - operator==(const simd_fast_mersenne_twister_engine& __lhs, - const simd_fast_mersenne_twister_engine& __rhs) - { return (std::equal(__lhs._M_stateT, __lhs._M_stateT + state_size, - __rhs._M_stateT) - && __lhs._M_pos == __rhs._M_pos); } -#endif + template + friend bool + operator==(const simd_fast_mersenne_twister_engine<_UIntType_2, + __m_2, __pos1_2, __sl1_2, __sl2_2, __sr1_2, __sr2_2, + __msk1_2, __msk2_2, __msk3_2, __msk4_2, + __parity1_2, __parity2_2, __parity3_2, __parity4_2>& __lhs, + const simd_fast_mersenne_twister_engine<_UIntType_2, + __m_2, __pos1_2, __sl1_2, __sl2_2, __sr1_2, __sr2_2, + __msk1_2, __msk2_2, __msk3_2, __msk4_2, + __parity1_2, __parity2_2, __parity3_2, __parity4_2>& __rhs); template - inline __m128i __sse2_recursion(__m128i __a, __m128i __b, - __m128i __c, __m128i __d) - { - __m128i __y = _mm_srli_epi32(__b, __sr1); - __m128i __z = _mm_srli_si128(__c, __sr2); - __m128i __v = _mm_slli_epi32(__d, __sl1); - __z = _mm_xor_si128(__z, __a); - __z = _mm_xor_si128(__z, __v); - __m128i __x = _mm_slli_si128(__a, __sl2); - __y = _mm_and_si128(__y, _mm_set_epi32(__msk4, __msk3, __msk2, __msk1)); - __z = _mm_xor_si128(__z, __x); - return _mm_xor_si128(__z, __y); - } - - } - - - template - void simd_fast_mersenne_twister_engine<_UIntType, __m, - __pos1, __sl1, __sl2, __sr1, __sr2, - __msk1, __msk2, __msk3, __msk4, - __parity1, __parity2, __parity3, - __parity4>:: - _M_gen_rand(void) - { - __m128i __r1 = _mm_load_si128(&_M_state[_M_nstate - 2]); - __m128i __r2 = _mm_load_si128(&_M_state[_M_nstate - 1]); - - size_t __i; - for (__i = 0; __i < _M_nstate - __pos1; ++__i) - { - __m128i __r = __sse2_recursion<__sl1, __sl2, __sr1, __sr2, - __msk1, __msk2, __msk3, __msk4> - (_M_state[__i], _M_state[__i + __pos1], __r1, __r2); - _mm_store_si128(&_M_state[__i], __r); - __r1 = __r2; - __r2 = __r; - } - for (; __i < _M_nstate; ++__i) - { - __m128i __r = __sse2_recursion<__sl1, __sl2, __sr1, __sr2, - __msk1, __msk2, __msk3, __msk4> - (_M_state[__i], _M_state[__i + __pos1 - _M_nstate], __r1, __r2); - _mm_store_si128(&_M_state[__i], __r); - __r1 = __r2; - __r2 = __r; - } - - _M_pos = 0; - } - - -#else - - namespace { - template inline void __rshift(uint32_t *__out, const uint32_t *__in) { @@ -374,6 +310,29 @@ #endif +#ifndef _GLIBCXX_OPT_HAVE_RANDOM_SFMT_OPERATOREQUAL + template + bool + operator==(const __gnu_cxx::simd_fast_mersenne_twister_engine<_UIntType, + __m, __pos1, __sl1, __sl2, __sr1, __sr2, + __msk1, __msk2, __msk3, __msk4, + __parity1, __parity2, __parity3, __parity4>& __lhs, + const __gnu_cxx::simd_fast_mersenne_twister_engine<_UIntType, + __m, __pos1, __sl1, __sl2, __sr1, __sr2, + __msk1, __msk2, __msk3, __msk4, + __parity1, __parity2, __parity3, __parity4>& __rhs) + { + return (std::equal(__lhs._M_stateT, __lhs._M_stateT + state_size, + __rhs._M_stateT) + && __lhs._M_pos == __rhs._M_pos); + } +#endif template. + +/** @file ext/random.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{ext/random} + */ + +#ifndef _EXT_OPT_RANDOM_H +#define _EXT_OPT_RANDOM_H 1 + +#pragma GCC system_header + + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + namespace { + + template + inline __m128i __sse2_recursion(__m128i __a, __m128i __b, + __m128i __c, __m128i __d) + { + __m128i __y = _mm_srli_epi32(__b, __sr1); + __m128i __z = _mm_srli_si128(__c, __sr2); + __m128i __v = _mm_slli_epi32(__d, __sl1); + __z = _mm_xor_si128(__z, __a); + __z = _mm_xor_si128(__z, __v); + __m128i __x = _mm_slli_si128(__a, __sl2); + __y = _mm_and_si128(__y, _mm_set_epi32(__msk4, __msk3, __msk2, __msk1)); + __z = _mm_xor_si128(__z, __x); + return _mm_xor_si128(__z, __y); + } + + } + + +#define _GLIBCXX_OPT_HAVE_RANDOM_SFMT_GEN_READ 1 + template + void simd_fast_mersenne_twister_engine<_UIntType, __m, + __pos1, __sl1, __sl2, __sr1, __sr2, + __msk1, __msk2, __msk3, __msk4, + __parity1, __parity2, __parity3, + __parity4>:: + _M_gen_rand(void) + { + __m128i __r1 = _mm_load_si128(&_M_state[_M_nstate - 2]); + __m128i __r2 = _mm_load_si128(&_M_state[_M_nstate - 1]); + + size_t __i; + for (__i = 0; __i < _M_nstate - __pos1; ++__i) + { + __m128i __r = __sse2_recursion<__sl1, __sl2, __sr1, __sr2, + __msk1, __msk2, __msk3, __msk4> + (_M_state[__i], _M_state[__i + __pos1], __r1, __r2); + _mm_store_si128(&_M_state[__i], __r); + __r1 = __r2; + __r2 = __r; + } + for (; __i < _M_nstate; ++__i) + { + __m128i __r = __sse2_recursion<__sl1, __sl2, __sr1, __sr2, + __msk1, __msk2, __msk3, __msk4> + (_M_state[__i], _M_state[__i + __pos1 - _M_nstate], __r1, __r2); + _mm_store_si128(&_M_state[__i], __r); + __r1 = __r2; + __r2 = __r; + } + + _M_pos = 0; + } + + +#define _GLIBCXX_OPT_HAVE_RANDOM_SFMT_OPERATOREQUAL 1 + template + bool + operator==(const __gnu_cxx::simd_fast_mersenne_twister_engine<_UIntType, + __m, __pos1, __sl1, __sl2, __sr1, __sr2, + __msk1, __msk2, __msk3, __msk4, + __parity1, __parity2, __parity3, __parity4>& __lhs, + const __gnu_cxx::simd_fast_mersenne_twister_engine<_UIntType, + __m, __pos1, __sl1, __sl2, __sr1, __sr2, + __msk1, __msk2, __msk3, __msk4, + __parity1, __parity2, __parity3, __parity4>& __rhs) + { + __m128i __res = _mm_cmpeq_epi8(__lhs._M_state[0], __rhs._M_state[0]); + for (size_t __i = 1; __i < __lhs._M_nstate; ++__i) + __res = _mm_and_si128(__res, _mm_cmpeq_epi8(__lhs._M_state[__i], + __rhs._M_state[__i])); + return (_mm_movemask_epi8(__res) == 0xffff + && __lhs._M_pos == __rhs._M_pos); + } + + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + + +#endif // _EXT_OPT_RANDOM_H --- /dev/null 2012-08-25 17:45:56.293307003 -0400 +++ config/cpu/generic/opt/ext/opt_random.h 2012-09-08 11:41:32.698833206 -0400 @@ -0,0 +1,38 @@ +// Optimizations for random number extensions, generic version -*- C++ -*- + +// Copyright (C) 2012 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/random.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{ext/random} + */ + +#ifndef _EXT_OPT_RANDOM_H +#define _EXT_OPT_RANDOM_H 1 + +#pragma GCC system_header + + + + +#endif // _EXT_OPT_RANDOM_H