Simon Jenkins wrote:
[...]If it still doesn't
work after they are applied then you could try -ffloat-store. The
compiler manual
says that programs which rely on the exact storage format of IEEE
floats should
use this option, but I am unable to break the macro in a way that this
fixes.
Unfortunately -ffloat-store slows code down a *lot*.
More unfortunately, I can't prove that the macro will always function
correctly
without it. I still can't actually break it, but things I have read
whilst searching
the web have given me definite cause for concern that it could fail.
I might mail a compiler list about this one.
I'm hoping to post some code in the next day or
two which prevents
denormal
values from being generated in the first place.
Here's where I've got to so far. Comments are welcome.
(Note: This might, or might not, suffer from the same problems that
FLUSH_TO_ZERO
might or might not suffer from :))
/* === benormal.h - Copyright (C) 2003 Simon Jenkins === */
#define FLOAT_EXP_MASK (0x7F800000)
#define FLOAT_AS_BITS(x) (*(volatile unsigned int *)&(x))
/*============================================================================
Function: FlushMultiplyQuick
==============================================================================
Purpose: Returns the product of its parameters, but flushes the result to
zero if there is suspicion (not proof!) that the result
might have
been a denormal float.
Method: The result is flushed to zero if the magnitude of either
parameter
is below 2**-63.
Comments: This never produces a denormal, but sometimes flushes a result
that would not have been denormal.
============================================================================*/
static inline float FlushMultiplyQuick( float a, float b )
{
return ( ( FLOAT_AS_BITS(a) & 0x60000000 )
&& ( FLOAT_AS_BITS(b) & 0x60000000 ) )
? (a * b) : 0.0f;
}
/*============================================================================
Function: FlushMultiplyQuickAsym
==============================================================================
Purpose: Returns the product of its parameters, but flushes the result to
zero if there is suspicion (not proof!) that the result
might have
been a denormal float.
Method: The result is flushed to zero if the magnitude of the first
parameter is below 2**-63.
Comments: Faster than FlushMultiplyQuick, but might produce a denormal if
the second parameter is non-zero with magnitude < 2**-63. Never
produces a denormal if second parameter has magnitude >= 2**-63,
============================================================================*/
static inline float FlushMultiplyQuickAsym( float a, float b )
{
return ( FLOAT_AS_BITS(a) & 0x60000000 ) ? (a * b) : 0.0f;
}
/*============================================================================
Function: FlushMultiply
==============================================================================
Purpose: Returns the product of its parameters, but flushes the result to
zero if there is suspicion (not proof!) that the result
might have
been a denormal float.
Method: Computes a lower bound for the exponent of the result by adding
the exponents of the parameters. Flushes the result if the lower
bound suggests a possible denormal result.
Comments: A bit slower than the other methods, but much less likely to
flush
a non-denormal result. (A non-denormal will only be flushed
if the
mantissas of the parameters would have "saved" an otherwise
denormal result by having a product >= 2). Never produces a
denormal result.
============================================================================*/
static inline float FlushMultiply( float a, float b )
{
return ( ( FLOAT_AS_BITS(a) & FLOAT_EXP_MASK )
+ ( FLOAT_AS_BITS(b) & FLOAT_EXP_MASK ) > 0x3F800000 )
? (a * b) : 0.0f;
}
/*=== end of file ===*/
Simon Jenkins
(Bristol, UK)