[Mesa-dev] [PATCH 1/2] mesa: reimplement IROUND(), add F_TO_I()

Ian Romanick idr at freedesktop.org
Fri May 18 15:55:08 PDT 2012


On 05/18/2012 02:10 PM, Brian Paul wrote:
> The different implementations of IROUND() behaved differently and in
> the case of fistp, depended on the current x86 FPU rounding mode.
> This caused some tests like piglit roundmode-pixelstore and
> roundmode-getintegerv to fail on 32-bit x86 but pass on 64-bit x86.
>
> Now IROUND() always rounds to the nearest integer (away from zero).
> The new F_TO_I function converts a float to an int by whatever means
> is fastest.  We'll use this where we're more concerned with performance
> and not too worried to how the conversion is done.
> ---
>   src/mesa/main/imports.h |   57 +++++++++++++++++++++++++++++-----------------
>   1 files changed, 36 insertions(+), 21 deletions(-)
>
> diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h
> index aa5eb32..c0b6cec 100644
> --- a/src/mesa/main/imports.h
> +++ b/src/mesa/main/imports.h
> @@ -285,19 +285,47 @@ static inline int GET_FLOAT_BITS( float x )
>   #endif
>
>
> -/***
> - *** IROUND: return (as an integer) float rounded to nearest integer
> - ***/
> +/**
> + * Convert float to int by rounding to nearest integer, away from zero.
> + */
> +static inline int IROUND(float f)
> +{
> +   return (int) ((f>= 0.0F) ? (f + 0.5F) : (f - 0.5F));

Whenever I see code like this, I wonder if it should use signbit instead 
of comparing with zero.  Since this is the same code that was already in 
Mesa, it shouldn't really change anything.  I'm just always suspicious 
of floating point comparison code.

> +}
> +
> +
> +/**
> + * Convert float to int64 by rounding to nearest integer.
> + */
> +static inline GLint64 IROUND64(float f)
> +{
> +   return (GLint64) ((f>= 0.0F) ? (f + 0.5F) : (f - 0.5F));
> +}
> +
> +
> +/**
> + * Convert positive float to int by rounding to nearest integer.
> + */
> +static inline int IROUND_POS(float f)
> +{
> +   assert(f>= 0.0F);
> +   return (int) (f + 0.5F);
> +}
> +
> +
> +/**
> + * Convert float to int using a fast method.  The rounding mode may vary.
> + * XXX We could use an x86-64/SSE2 version here.
> + */
>   #if defined(USE_X86_ASM)&&  defined(__GNUC__)&&  defined(__i386__)
> -static inline int iround(float f)
> +static inline int F_TO_I(float f)
>   {
>      int r;
>      __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
>      return r;
>   }
> -#define IROUND(x)  iround(x)
>   #elif defined(USE_X86_ASM)&&  defined(_MSC_VER)
> -static inline int iround(float f)
> +static inline int F_TO_I(float f)
>   {
>      int r;
>      _asm {
> @@ -306,9 +334,8 @@ static inline int iround(float f)
>   	}
>      return r;
>   }
> -#define IROUND(x)  iround(x)
>   #elif defined(__WATCOMC__)&&  defined(__386__)
> -long iround(float f);
> +long F_TO_I(float f);
>   #pragma aux iround =                    \
>   	"push   eax"                        \
>   	"fistp  dword ptr [esp]"            \
> @@ -316,20 +343,8 @@ long iround(float f);
>   	parm [8087]                         \
>   	value [eax]                         \
>   	modify exact [eax];
> -#define IROUND(x)  iround(x)
> -#else
> -#define IROUND(f)  ((int) (((f)>= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))
> -#endif
> -
> -#define IROUND64(f)  ((GLint64) (((f)>= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))
> -
> -/***
> - *** IROUND_POS: return (as an integer) positive float rounded to nearest int
> - ***/
> -#ifdef DEBUG
> -#define IROUND_POS(f) (assert((f)>= 0.0F), IROUND(f))
>   #else
> -#define IROUND_POS(f) (IROUND(f))
> +#define F_TO_I(f)  IROUND(f)
>   #endif
>
>



More information about the mesa-dev mailing list