Mercurial > jwe > octave
diff liboctave/util/oct-inttypes.h @ 25846:144820478378 stable
eliminate OCTAVE_HAVE_FAST_INT_OPS macro and associated code (bug #54572)
With current compilers, there no longer seems to be a performance
advantage significant enough to justify the the trickery used in the
special case code that was used when OCTAVE_HAVE_FAST_INT_OPS was
defined.
* acinclude.m4 (OCTAVE_FAST_INT_OPS): Delete macro.
* configure.ac: Delete use.
* mk-octave-config-h.sh: Don't recognize OCTAVE_HAVE_FAST_INT_OPS.
* oct-inttypes.h, oct-inttypes.cc:
(octave_int_arith_base<T,true>::abs,
octave_int_arith_base<T,true>::minus,
octave_int_arith_base<T,true>::add,
octave_int_arith_base<T,true>::sub):
Eliminate code blocks used if OCTAVE_HAVE_FAST_INT_OPS is defined.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 30 Aug 2018 10:03:09 -0400 |
parents | 26c41d8bf170 |
children | dd10eea0be97 1f52a96c8c21 |
line wrap: on
line diff
--- a/liboctave/util/oct-inttypes.h Wed Aug 29 14:33:36 2018 -0700 +++ b/liboctave/util/oct-inttypes.h Thu Aug 30 10:03:09 2018 -0400 @@ -507,32 +507,6 @@ #endif -// Signed integer arithmetic. -// -// Rationale: If OCTAVE_HAVE_FAST_INT_OPS is defined, the following -// conditions should hold: -// -// 1. Signed numbers are represented by twos complement (see -// <http://en.wikipedia.org/wiki/Two%27s_complement>) -// -// 2. static_cast to unsigned int counterpart works like -// interpreting the signed bit pattern as unsigned (and is thus -// zero-cost). -// -// 3. Signed addition and subtraction yield the same bit results as -// unsigned. (We use casts to prevent optimization interference, -// so there is no need for things like -ftrapv). -// -// 4. Bit operations on signed integers work like on unsigned -// integers, except for the shifts. Shifts are arithmetic. -// -// The above conditions are satisfied by most modern platforms. If -// OCTAVE_HAVE_FAST_INT_OPS is defined, bit tricks and wraparound -// arithmetics are used to avoid conditional jumps as much as -// possible, thus being friendly to modern pipeline processor -// architectures. Otherwise, we fall back to a bullet-proof code that -// only uses assumptions guaranteed by the standard. - template <typename T> class octave_int_arith_base<T, true> : octave_int_base<T> { @@ -550,32 +524,16 @@ static T abs (T x) { -#if defined (OCTAVE_HAVE_FAST_INT_OPS) - // This is close to how GCC does std::abs, but we can't just use std::abs, - // because its behavior for INT_MIN is undefined and the compiler could - // discard the following test. - T m = x >> std::numeric_limits<T>::digits; - T y = (x ^ m) - m; - if (y < 0) - { - y = octave_int_base<T>::max_val (); - } - return y; -#else - // -INT_MAX is safe because C++ actually allows only three implementations - // of integers: sign & magnitude, ones complement and twos complement. - // The first test will, with modest optimizations, evaluate at compile - // time, and maybe eliminate the branch completely. - T y; - if (octave_int_base<T>::min_val () < -octave_int_base<T>::max_val () - && x == octave_int_base<T>::min_val ()) - { - y = octave_int_base<T>::max_val (); - } - else - y = (x < 0) ? -x : x; - return y; -#endif + // -INT_MAX is safe because C++ actually allows only three + // implementations of integers: sign & magnitude, ones complement + // and twos complement. The first test will, with modest + // optimizations, evaluate at compile time, and maybe eliminate + // the branch completely. + + return ((octave_int_base<T>::min_val () < -octave_int_base<T>::max_val () + && x == octave_int_base<T>::min_val ()) + ? octave_int_base<T>::max_val () + : ((x < 0) ? -x : x)); } static T @@ -596,114 +554,42 @@ lshift (T x, int n) { return x << n; } // Minus has problems similar to abs. + static T minus (T x) { -#if defined (OCTAVE_HAVE_FAST_INT_OPS) - T y = -x; - if (y == octave_int_base<T>::min_val ()) - { - --y; - } - return y; -#else - T y; - if (octave_int_base<T>::min_val () < -octave_int_base<T>::max_val () - && x == octave_int_base<T>::min_val ()) - { - y = octave_int_base<T>::max_val (); - } - else - y = -x; - return y; -#endif + return ((octave_int_base<T>::min_val () < -octave_int_base<T>::max_val () + && x == octave_int_base<T>::min_val ()) + ? octave_int_base<T>::max_val () + : -x); } static T add (T x, T y) { -#if defined (OCTAVE_HAVE_FAST_INT_OPS) - - // The typecasts do nothing, but they are here to prevent an optimizing - // compiler from interfering. Also, the signed operations on small types - // actually return int. - T u = static_cast<UT> (x) + static_cast<UT> (y); - T ux = u ^ x; - T uy = u ^ y; - - return ((ux & uy) < 0 - ? (u < 0 - ? octave_int_base<T>::max_val () - : octave_int_base<T>::min_val ()) - : u); - -#else + // Avoid anything that may overflow. - // We shall carefully avoid anything that may overflow. - T u; - - if (y < 0) - { - if (x < octave_int_base<T>::min_val () - y) - u = octave_int_base<T>::min_val (); - else - u = x + y; - } - else - { - if (x > octave_int_base<T>::max_val () - y) - u = octave_int_base<T>::max_val (); - else - u = x + y; - } - - return u; - -#endif + return (y < 0 + ? (x < octave_int_base<T>::min_val () - y + ? octave_int_base<T>::min_val () + : x + y) + : (x > octave_int_base<T>::max_val () - y + ? octave_int_base<T>::max_val () + : x + y)); } - // This is very similar to addition. static T sub (T x, T y) { -#if defined (OCTAVE_HAVE_FAST_INT_OPS) - // The typecasts do nothing, but they are here to prevent an optimizing - // compiler from interfering. Also, the signed operations on small types - // actually return int. - T u = static_cast<UT> (x) - static_cast<UT> (y); - T ux = u ^ x; - T uy = u ^ ~y; - if ((ux & uy) < 0) - { - u = (__signbit (~u) - ? octave_int_base<T>::min_val () - : octave_int_base<T>::max_val ()); - } - return u; -#else - // We shall carefully avoid anything that may overflow. - T u; - if (y < 0) - { - if (x > octave_int_base<T>::max_val () + y) - { - u = octave_int_base<T>::max_val (); - } - else - u = x - y; - } - else - { - if (x < octave_int_base<T>::min_val () + y) - { - u = octave_int_base<T>::min_val (); - } - else - u = x - y; - } + // Avoid anything that may overflow. - return u; -#endif + return (y < 0 + ? (x > octave_int_base<T>::max_val () + y + ? octave_int_base<T>::max_val () + : x - y) + : (x < octave_int_base<T>::min_val () + y + ? octave_int_base<T>::min_val () + : x - y)); } // Multiplication is done using promotion to wider integer type. If there is @@ -803,9 +689,6 @@ long double p = static_cast<long double> (x) * static_cast<long double> (y); - // NOTE: We could maybe do it with a single branch if - // OCTAVE_HAVE_FAST_INT_OPS, but it would require one more runtime - // conversion, so the question is whether it would really be faster. if (p > static_cast<long double> (octave_int_base<int64_t>::max_val ())) retval = octave_int_base<int64_t>::max_val (); else if (p < static_cast<long double> (octave_int_base<int64_t>::min_val ()))