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

Roland Scheidegger sroland at vmware.com
Fri May 18 14:54:57 PDT 2012


Looks ok though I wonder if we really need our own assembly here?
In particular if the compiler decides to use sse we really shouldn't use
the fp stack for converting floats to ints. fistp is just twice as slow
as sse conversion on newer cpus, and additionally it might potentially
involve moving values from xmm regs to fp.
I suspect something like lroundf() would generate better code than the
manual assembly (and far better than the c code) if things are compiled
to use sse2 at least (the same is of course true for the other functions
like ceil etc.). But I guess that's not available everywhere...

Roland


Am 18.05.2012 23:10, schrieb Brian Paul:
> 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));
> +}
> +
> +
> +/**
> + * 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