This is the mail archive of the
mailing list for the GCC project.
Q: middle-end problem when variadic builtins promote float to double
- From: "Kaveh R. GHAZI" <ghazi at caip dot rutgers dot edu>
- To: gcc at gcc dot gnu dot org
- Date: Fri, 6 Jul 2007 17:12:13 -0400 (EDT)
- Subject: Q: middle-end problem when variadic builtins promote float to double
I have a question relating to variadic builtins and floating point
arguments. I'm trying to implement "isnormal" like so:
Basically, I change __builtin_isnormal(x) ->
isgreaterequal(fabs(x),FP_MIN) & islessequal(fabs(x),FP_MAX)
(where FP_MIN/FP_MAX are the respective min and max values that the type
of 'x' could contain. And fabs may be fabsl/fabsf as necessary.)
The builtin has a variadic prototype to faciliate accepting any FP type as
an argument. The problem arises when isnormal is passed a float
parameter, which according to C promotion rules is cast to double.
Inside the middle-end, the builtin sees the type as double. I don't
believe you can tell the difference between a promoted float and a
Normally, this is merely a performance penalty as the float is widened
unecessarily and the comparisons, etc are done in the wider mode. However
if isnormal is passed a subnormal float, e.g. FLT_MAX/2, if it's widened
to a double, then the number suddenly becomes "normal" again because of
the wider range of double types. Now we return incorrect results because
isgreaterequal(FLT_MIN/2,DBL_MIN) returns true.
My original patch above actually checks that FLT_MIN/2 is correctly
identified in the testcase. So I spent a lot of time scratching my head
why it was aborting in another file I was working on. Long story short,
the testcase in the patch above uses -funsafe-math-optimizations. This
doesn't change the resulting assembler code output. However on sparc it
activates crtfastmath.c. That in turn changes the FP behavior for sparc
to truncate all subnormal numbers to zero. Presto, testcase passes
because FLT_MIN/2 becomes zero before being cast to double and therefore
maintains that it is not "normal".
So how do we detect or work around this promotion issue and discriminate
between the case where a float is promoted because of the variadic
prototype vs a user supplied cast or other user code?
Kaveh R. Ghazi firstname.lastname@example.org