[Mesa-dev] [PATCH 3/3] util: Optimize _mesa_roundeven with SSE 4.1.

Ilia Mirkin imirkin at alum.mit.edu
Thu Mar 12 13:11:34 PDT 2015


On Thu, Mar 12, 2015 at 3:11 PM, Matt Turner <mattst88 at gmail.com> wrote:
> The SSE 4.1 ROUND instructions let us implement roundeven directly.
> Otherwise we assume that the rounding mode has not been modified (as we
> do in the rest of Mesa) and use rint().
>
> glibc uses the ROUND instruction in rint() after a cpuid check. This
> patch just lets us inline it directly when we're already building for
> SSE 4.1.
> ---
>  src/util/rounding.h | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>
> diff --git a/src/util/rounding.h b/src/util/rounding.h
> index d128524..e82fb59 100644
> --- a/src/util/rounding.h
> +++ b/src/util/rounding.h
> @@ -23,6 +23,10 @@
>
>  #include <math.h>
>
> +#ifdef __SSE4_1__
> +#include <smmintrin.h>
> +#endif
> +
>  /* The C standard library has functions round()/rint()/nearbyint() that round
>   * their arguments according to the rounding mode set in the floating-point
>   * control register. While there are trunc()/ceil()/floor() functions that do
> @@ -38,10 +42,16 @@ static inline float
>  _mesa_roundevenf(float x)
>  {
>     float ret;
> +#ifdef __SSE4_1__
> +   __m128 m = _mm_load_ss(&x);
> +   m = _mm_round_ss(m, m, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
> +   _mm_store_ss(&ret, m);

As we discussed, this will work differently than glibc depending on
the rounding mode set. Either use the same rounding mode that glibc
would use, or add an assert that the rounding mode is set the way you
expect (and if it doesn't work on msvc, then... wtvr. That's what
ifdef's are for.)

> +#else
>     /* Assume that the floating-point rounding mode has not been changed from
>      * the default (Round to nearest).
>      */
>     ret = rintf(x);
> +#endif
>     return ret;
>  }
>
> @@ -49,9 +59,15 @@ static inline double
>  _mesa_roundeven(double x)
>  {
>     double ret;
> +#ifdef __SSE4_1__
> +   __m128d m = _mm_load_sd(&x);
> +   m = _mm_round_sd(m, m, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
> +   _mm_store_sd(&ret, m);
> +#else
>     /* Assume that the floating-point rounding mode has not been changed from
>      * the default (Round to nearest).
>      */
>     ret = rint(x);
> +#endif
>     return ret;
>  }
> --
> 2.0.5
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list