On 28/04/16 16:49, Joseph Myers wrote:
On Thu, 28 Apr 2016, Matthew Wahab wrote:
Hello,
The ARM target supports the half-precision floating point type __fp16
but does not allow its use as a function return or parameter type. This
patch removes that restriction and defines the ACLE macro
__ARM_FP16_ARGS to indicate this. The code generated for passing __fp16
values into and out of functions depends on the level of hardware
support but conforms to the AAPCS (see
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf).
The sole use of the TARGET_INVALID_PARAMETER_TYPE and
TARGET_INVALID_RETURN_TYPE hooks was to disallow __fp16 use as a function
return or parameter type. Thus, I think this patch should completely
remove those hooks and poison them in system.h.
This patch addresses one incompatibility of the original __fp16
specification with the more recent ACLE specification and the
specification in ISO/IEC TS 18661-3 for how such types should work.
Another such incompatibility is the peculiar rule in the original
specification that conversions from double to __fp16 go via float, with
double rounding. Do you have plans to eliminate that and move to the
single-rounding semantics that are in current specifications?
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf
Section 4.1.2 states that double to fp16 should round only once and it only
suggests that it is done via a two step hardware instruction rather than an
emulation library if speed is the priority as pre-ARMv8 architectures do not
support this in hardware.
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053d/IHI0053D_acle_2_1.pdf
updates this paragraph to reflect ARMv8 hardware feature, but still maintains
the suggestion of using two-step hardware instruction rather than emulation
library if speed is priority for pre-ARMv8 architectures.
AFAICS, I don't think it mandates a double-rounding behavior for double to
__fp16 conversions and I don't see a change in stand between the two versions of
ACLE on the behavior of __fp16.
We could improve the ACLE spec to include a caveat that a two-step reduction
could introduce a loss in precision which could result in incompatibility with
ARMv8 architectures.
I note that that AAPCS revision says for __fp16, in 7.1.1 Arithmetic
Types, "In a variadic function call this will be passed as a
double-precision value.". I haven't checked what this patch implements,
but that could be problematic, and different from what's said under 7.2,
"For variadic functions, float arguments that match the ellipsis (...) are
converted to type double.".
In TS 18661-3, _Float16 is *not* affected by default argument promotions;
only float is. This reflects how the default conversion of float to
double is a legacy feature; note for example how in C99 and C11 float
_Imaginary is not promoted to double _Imaginary, and float _Complex is not
promoted to double _Complex.
Thus it would be better for compatibility with TS 18661-3 to pass __fp16
values to variadic functions as themselves, unpromoted. (Formally of
course the lack of promotion is a language feature not an ABI feature; as
long as va_arg for _Float16 named works correctly, you could promote at
the ABI level and then convert back, and the only effect would be that
sNaNs get quieted, so passing a _Float16 sNaN through variable arguments
would act as a convertFormat operation instead of a copy operation. It's
not clear that having such an ABI-level promotion is a good idea,
however.)
Now, in the context of the current implementation and current ACLE
arithmetic on __fp16 values produces float results - the operands are
promoted at the C language level. This is different from TS 18661-3,
where _Float16 arithmetic produces results whose semantics type is
_Float16 but which, if FLT_EVAL_METHOD is 0, are evaluated with excess
range and precision to the range and precision of float. So if __fp16 and
float are differently passed to variadic functions, you have the issue
that if the argument is an expression resulting from __fp16 arithmetic,
the way it is passed depends on whether current ACLE or TS 18661-3 are
followed. But if the eventual aim is for __fp16 (when using the IEEE
format rather than the alternative format) to become just a typedef for
_Float16, then these issues will need to be addressed.
__fp16's compatibility with _Float16 is still under discussion internally.
Thanks,
Tejas.