[Patch AArch64 13/17] Enable _Float16 for AArch64

gcc/

	* config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Update
	__FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_C99__ when we switch
	architecture levels.
	* config/aarch64/aarch64.c (aarch64_promoted_type): Only promote
	the aarch64_fp16_type_node, not all HFmode types.
	(aarch64_libgcc_floating_mode_supported_p): Support HFmode.
	(aarch64_scalar_mode_supported_p): Likewise.
	(aarch64_excess_precision): New.
	(TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Define.
	(TARGET_SCALAR_MODE_SUPPORTED_P): Likewise.
	(TARGET_C_EXCESS_PRECISION): Likewise.

gcc/testsuite/

	* gcc.target/aarch64/_Float16_1.c: New.
	* gcc.target/aarch64/_Float16_2.c: Likewise.
	* gcc.target/aarch64/_Float16_3.c: Likewise.

From-SVN: r242845
This commit is contained in:
James Greenhalgh 2016-11-24 18:19:29 +00:00 committed by James Greenhalgh
parent 2e5f8203d2
commit 11e554b3b5
7 changed files with 239 additions and 2 deletions

View File

@ -1,3 +1,17 @@
2016-11-24 James Greenhalgh <james.greenhalgh@arm.com>
* config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Update
__FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_C99__ when we switch
architecture levels.
* config/aarch64/aarch64.c (aarch64_promoted_type): Only promote
the aarch64_fp16_type_node, not all HFmode types.
(aarch64_libgcc_floating_mode_supported_p): Support HFmode.
(aarch64_scalar_mode_supported_p): Likewise.
(aarch64_excess_precision): New.
(TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Define.
(TARGET_SCALAR_MODE_SUPPORTED_P): Likewise.
(TARGET_C_EXCESS_PRECISION): Likewise.
2016-11-24 James Greenhalgh <james.greenhalgh@arm.com>
* config/aarch64/aarch64-c.c (aarch64_scalar_mode_supported_p): New.

View File

@ -133,6 +133,16 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
aarch64_def_or_undef (TARGET_CRYPTO, "__ARM_FEATURE_CRYPTO", pfile);
aarch64_def_or_undef (TARGET_SIMD_RDMA, "__ARM_FEATURE_QRDMX", pfile);
/* Not for ACLE, but required to keep "float.h" correct if we switch
target between implementations that do or do not support ARMv8.2-A
16-bit floating-point extensions. */
cpp_undef (pfile, "__FLT_EVAL_METHOD__");
builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
c_flt_eval_method (true));
cpp_undef (pfile, "__FLT_EVAL_METHOD_C99__");
builtin_define_with_int_value ("__FLT_EVAL_METHOD_C99__",
c_flt_eval_method (false));
}
/* Implement TARGET_CPU_CPP_BUILTINS. */

View File

@ -14240,12 +14240,20 @@ aarch64_vec_fpconst_pow_of_2 (rtx x)
return firstval;
}
/* Implement TARGET_PROMOTED_TYPE to promote __fp16 to float. */
/* Implement TARGET_PROMOTED_TYPE to promote 16-bit floating point types
to float.
__fp16 always promotes through this hook.
_Float16 may promote if TARGET_FLT_EVAL_METHOD is 16, but we do that
through the generic excess precision logic rather than here. */
static tree
aarch64_promoted_type (const_tree t)
{
if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
if (SCALAR_FLOAT_TYPE_P (t)
&& TYPE_MAIN_VARIANT (t) == aarch64_fp16_type_node)
return float_type_node;
return NULL_TREE;
}
@ -14265,6 +14273,17 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
}
}
/* Implement TARGET_LIBGCC_FLOATING_POINT_MODE_SUPPORTED_P - return TRUE
if MODE is HFmode, and punt to the generic implementation otherwise. */
static bool
aarch64_libgcc_floating_mode_supported_p (machine_mode mode)
{
return (mode == HFmode
? true
: default_libgcc_floating_mode_supported_p (mode));
}
/* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE
if MODE is HFmode, and punt to the generic implementation otherwise. */
@ -14276,6 +14295,47 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
: default_scalar_mode_supported_p (mode));
}
/* Set the value of FLT_EVAL_METHOD.
ISO/IEC TS 18661-3 defines two values that we'd like to make use of:
0: evaluate all operations and constants, whose semantic type has at
most the range and precision of type float, to the range and
precision of float; evaluate all other operations and constants to
the range and precision of the semantic type;
N, where _FloatN is a supported interchange floating type
evaluate all operations and constants, whose semantic type has at
most the range and precision of _FloatN type, to the range and
precision of the _FloatN type; evaluate all other operations and
constants to the range and precision of the semantic type;
If we have the ARMv8.2-A extensions then we support _Float16 in native
precision, so we should set this to 16. Otherwise, we support the type,
but want to evaluate expressions in float precision, so set this to
0. */
static enum flt_eval_method
aarch64_excess_precision (enum excess_precision_type type)
{
switch (type)
{
case EXCESS_PRECISION_TYPE_FAST:
case EXCESS_PRECISION_TYPE_STANDARD:
/* We can calculate either in 16-bit range and precision or
32-bit range and precision. Make that decision based on whether
we have native support for the ARMv8.2-A 16-bit floating-point
instructions or not. */
return (TARGET_FP_F16INST
? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
case EXCESS_PRECISION_TYPE_IMPLICIT:
return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
default:
gcc_unreachable ();
}
return FLT_EVAL_METHOD_UNPREDICTABLE;
}
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST aarch64_address_cost
@ -14354,6 +14414,9 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
#undef TARGET_BUILTIN_RECIPROCAL
#define TARGET_BUILTIN_RECIPROCAL aarch64_builtin_reciprocal
#undef TARGET_C_EXCESS_PRECISION
#define TARGET_C_EXCESS_PRECISION aarch64_excess_precision
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
@ -14410,6 +14473,10 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
#undef TARGET_LIBGCC_CMP_RETURN_MODE
#define TARGET_LIBGCC_CMP_RETURN_MODE aarch64_libgcc_cmp_return_mode
#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \
aarch64_libgcc_floating_mode_supported_p
#undef TARGET_MANGLE_TYPE
#define TARGET_MANGLE_TYPE aarch64_mangle_type

View File

@ -1,3 +1,9 @@
2016-11-24 James Greenhalgh <james.greenhalgh@arm.com>
* gcc.target/aarch64/_Float16_1.c: New.
* gcc.target/aarch64/_Float16_2.c: Likewise.
* gcc.target/aarch64/_Float16_3.c: Likewise.
2016-11-24 James Greenhalgh <james.greenhalgh@arm.com>
* gcc.target/aarch64/floatdihf2_1.c: New.

View File

@ -0,0 +1,47 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=armv8.2-a+nofp16" } */
#pragma GCC target ("arch=armv8.2-a+nofp16")
_Float16
foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
__fp16
bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
#pragma GCC target ("arch=armv8.2-a+fp16")
_Float16
foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
__fp16
bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
/* Test that we merge to FMA operations. This indicates that we are not
making extraneous conversions between modes. */
/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82. */
/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
/* One FMA operation in 16-bit precision, from foo_v82. */
/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
/* Test that we are resetting the __FLT_EVAL_METHOD__. */
/* { dg-final { scan-assembler-times "mov\tw\[0-9\]\+, 16" 2 } } */
/* { dg-final { scan-assembler-times "str\twzr" 2 } } */

View File

@ -0,0 +1,47 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=armv8.2-a+nofp16 -fpermitted-flt-eval-methods=c11" } */
#pragma GCC target ("arch=armv8.2-a+nofp16")
_Float16
foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
__fp16
bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
#pragma GCC target ("arch=armv8.2-a+fp16")
_Float16
foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
__fp16
bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
/* Test that we merge to FMA operations. This indicates that we are not
making extraneous conversions between modes. */
/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82. */
/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
/* One FMA operation in 16-bit precision, from foo_v82. */
/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
/* Test that in -fpermitted-flt-eval-methods=c11 we don't set the
__FLT_EVAL_METHOD__ to anything other than 0. */
/* { dg-final { scan-assembler-times "str\twzr" 4 } } */

View File

@ -0,0 +1,46 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=armv8.2-a+nofp16 -std=c11 -ffp-contract=fast" } */
#pragma GCC target ("arch=armv8.2-a+nofp16")
_Float16
foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
__fp16
bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
#pragma GCC target ("arch=armv8.2-a+fp16")
_Float16
foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
__fp16
bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
{
*eval = __FLT_EVAL_METHOD__;
return x * x + y;
}
/* Test that we merge to FMA operations. This indicates that we are not
making extraneous conversions between modes. */
/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82. */
/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
/* One FMA operation in 16-bit precision, from foo_v82. */
/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
/* Test that in C11 mode, we don't reset __FLT_EVAL_METHOD__. */
/* { dg-final { scan-assembler-times "str\twzr" 4 } } */