This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] RFC for patch to add C99 fma/fmaf/fmal builtins
- From: "Joseph S. Myers" <joseph at codesourcery dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: Michael Meissner <meissner at linux dot vnet dot ibm dot com>, gcc-patches at gcc dot gnu dot org, dje dot gcc at gmail dot com
- Date: Mon, 4 Oct 2010 23:39:17 +0000 (UTC)
- Subject: Re: [PATCH] RFC for patch to add C99 fma/fmaf/fmal builtins
- References: <20101004204000.GA24432@hungry-tiger.westford.ibm.com> <4CAA422B.6010506@redhat.com>
On Mon, 4 Oct 2010, Richard Henderson wrote:
> On 10/04/2010 01:40 PM, Michael Meissner wrote:
> > My question is what should we do if the port has no FMA instruction?
> >
> > 1) Always call fma external (current behavior)
> > 2) Expand to (operand[0] * operand[1]) + operand[2] always
> > 3) Expand to (operand[0] * operand[1]) + operand[2] if -ffast-math
>
> (2) is clearly wrong, (3) I really don't have an opinion about.
>
> I seem to recall that double-rounding is ok as long as the intermediate
> step contains > 2N bits. Which implies that for IEEE single (23 bits)
> we can generically implement it with IEEE double (53 bits > 46):
>
> result = (float)((double)op0 * (double)op1) + (double)op2);
No, that's not safe. Say (double)op0 * (double)op1 has a value exactly
half way between two representable float values, and (double)op2 is much
smaller in magnitude, so that in round-to-nearest the above becomes
(float)((double)op0 * (double)op1) - but the correct float result depends
on the sign of the tiny op2.
If you have an operation "add two double values and round the
infinite-precision result just once to float" then you can do it that way.
I don't think such an operation is particularly common (as I recall, IA64
has it, but IA64 also has native fma).
--
Joseph S. Myers
joseph@codesourcery.com