From: James Greenhalgh Date: Wed, 23 Nov 2016 17:36:21 +0000 (+0000) Subject: [Patch ARM 17/17] Enable _Float16 for ARM and fix PR target/63250 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5774b1fa53437c221f295c9f0a28d32b5a629473;p=gcc.git [Patch ARM 17/17] Enable _Float16 for ARM and fix PR target/63250 gcc/ PR target/63250 * config/arm/arm-builtins.c (arm_simd_floatHF_type_node): Rename to... (arm_fp16_type_node): ...This, make visibile. (arm_simd_builtin_std_type): Rename arm_simd_floatHF_type_node to arm_fp16_type_node. (arm_init_simd_builtin_types): Likewise. (arm_init_fp16_builtins): Likewise. * config/arm/arm.c (arm_excess_precision): New. (arm_floatn_mode): Likewise. (TARGET_C_EXCESS_PRECISION): Likewise. (TARGET_FLOATN_MODE): Likewise. (arm_promoted_type): Only promote arm_fp16_type_node. * config/arm/arm.h (arm_fp16_type_node): Declare. gcc/testsuite/ PR target/63250 * lib/target-supports.exp (add_options_for_float16): Add -mfp16-format=ieee when testign arm*-*-*. From-SVN: r242784 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4ab87a9d009..600a9ef747a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2016-11-23 James Greenhalgh + + PR target/63250 + * config/arm/arm-builtins.c (arm_simd_floatHF_type_node): Rename to... + (arm_fp16_type_node): ...This, make visibile. + (arm_simd_builtin_std_type): Rename arm_simd_floatHF_type_node to + arm_fp16_type_node. + (arm_init_simd_builtin_types): Likewise. + (arm_init_fp16_builtins): Likewise. + * config/arm/arm.c (arm_excess_precision): New. + (arm_floatn_mode): Likewise. + (TARGET_C_EXCESS_PRECISION): Likewise. + (TARGET_FLOATN_MODE): Likewise. + (arm_promoted_type): Only promote arm_fp16_type_node. + * config/arm/arm.h (arm_fp16_type_node): Declare. + 2016-11-23 James Greenhalgh * config/arm/arm.c (arm_convert_to_type): Delete. diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index e73043db6db..5ed38d1608c 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -652,7 +652,8 @@ static struct arm_simd_type_info arm_simd_types [] = { }; #undef ENTRY -static tree arm_simd_floatHF_type_node = NULL_TREE; +/* The user-visible __fp16 type. */ +tree arm_fp16_type_node = NULL_TREE; static tree arm_simd_intOI_type_node = NULL_TREE; static tree arm_simd_intEI_type_node = NULL_TREE; static tree arm_simd_intCI_type_node = NULL_TREE; @@ -739,7 +740,7 @@ arm_simd_builtin_std_type (enum machine_mode mode, case XImode: return arm_simd_intXI_type_node; case HFmode: - return arm_simd_floatHF_type_node; + return arm_fp16_type_node; case SFmode: return float_type_node; case DFmode: @@ -840,8 +841,8 @@ arm_init_simd_builtin_types (void) /* Continue with standard types. */ /* The __builtin_simd{64,128}_float16 types are kept private unless we have a scalar __fp16 type. */ - arm_simd_types[Float16x4_t].eltype = arm_simd_floatHF_type_node; - arm_simd_types[Float16x8_t].eltype = arm_simd_floatHF_type_node; + arm_simd_types[Float16x4_t].eltype = arm_fp16_type_node; + arm_simd_types[Float16x8_t].eltype = arm_fp16_type_node; arm_simd_types[Float32x2_t].eltype = float_type_node; arm_simd_types[Float32x4_t].eltype = float_type_node; @@ -1754,11 +1755,11 @@ arm_init_iwmmxt_builtins (void) static void arm_init_fp16_builtins (void) { - arm_simd_floatHF_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (arm_simd_floatHF_type_node) = GET_MODE_PRECISION (HFmode); - layout_type (arm_simd_floatHF_type_node); + arm_fp16_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (arm_fp16_type_node) = GET_MODE_PRECISION (HFmode); + layout_type (arm_fp16_type_node); if (arm_fp16_format) - (*lang_hooks.types.register_builtin_type) (arm_simd_floatHF_type_node, + (*lang_hooks.types.register_builtin_type) (arm_fp16_type_node, "__fp16"); } diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 118b93b9430..74cb64ce789 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -266,6 +266,7 @@ static bool arm_builtin_support_vector_misalignment (machine_mode mode, int misalignment, bool is_packed); static void arm_conditional_register_usage (void); +static enum flt_eval_method arm_excess_precision (enum excess_precision_type); static reg_class_t arm_preferred_rename_class (reg_class_t rclass); static unsigned int arm_autovectorize_vector_sizes (void); static int arm_default_branch_cost (bool, bool); @@ -299,6 +300,7 @@ static bool arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num); static unsigned int arm_elf_section_type_flags (tree decl, const char *name, int reloc); static void arm_expand_divmod_libfunc (rtx, machine_mode, rtx, rtx, rtx *, rtx *); +static machine_mode arm_floatn_mode (int, bool); /* Table of machine attributes. */ static const struct attribute_spec arm_attribute_table[] = @@ -444,6 +446,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_ASM_INTERNAL_LABEL #define TARGET_ASM_INTERNAL_LABEL arm_internal_label +#undef TARGET_FLOATN_MODE +#define TARGET_FLOATN_MODE arm_floatn_mode + #undef TARGET_FUNCTION_OK_FOR_SIBCALL #define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall @@ -734,6 +739,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_EXPAND_DIVMOD_LIBFUNC #define TARGET_EXPAND_DIVMOD_LIBFUNC arm_expand_divmod_libfunc +#undef TARGET_C_EXCESS_PRECISION +#define TARGET_C_EXCESS_PRECISION arm_excess_precision + struct gcc_target targetm = TARGET_INITIALIZER; /* Obstack for minipool constant handling. */ @@ -22512,7 +22520,9 @@ arm_debugger_arg_offset (int value, rtx addr) static tree arm_promoted_type (const_tree t) { - if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16) + if (SCALAR_FLOAT_TYPE_P (t) + && TYPE_PRECISION (t) == 16 + && TYPE_MAIN_VARIANT (t) == arm_fp16_type_node) return float_type_node; return NULL_TREE; } @@ -22534,6 +22544,61 @@ arm_scalar_mode_supported_p (machine_mode mode) return 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 +arm_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_VFP_FP16INST + ? 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; +} + + +/* Implement TARGET_FLOATN_MODE. Make very sure that we don't provide + _Float16 if we are using anything other than ieee format for 16-bit + floating point. Otherwise, punt to the default implementation. */ +static machine_mode +arm_floatn_mode (int n, bool extended) +{ + if (!extended && n == 16) + return arm_fp16_format == ARM_FP16_FORMAT_IEEE ? HFmode : VOIDmode; + + return default_floatn_mode (n, extended); +} + + /* Set up OPERANDS for a register copy from SRC to DEST, taking care not to early-clobber SRC registers in the process. diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 15930f0ca8f..464710b2a98 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -73,6 +73,11 @@ extern int arm_ccfsm_state; extern GTY(()) rtx arm_target_insn; /* Callback to output language specific object attributes. */ extern void (*arm_lang_output_object_attributes_hook)(void); + +/* This type is the user-visible __fp16. We need it in a few places in + the backend. Defined in arm-builtins.c. */ +extern tree arm_fp16_type_node; + #undef CPP_SPEC #define CPP_SPEC "%(subtarget_cpp_spec) \ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0d5909052d4..0b5c3059214 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-11-23 James Greenhalgh + + PR target/63250 + * lib/target-supports.exp (add_options_for_float16): Add + -mfp16-format=ieee when testign arm*-*-*. + 2016-11-23 James Greenhalgh * gcc.target/arm/fp16-rounding-alt-1.c (ROUNDED): Change expected diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 624c2e29f7c..2192eb6539b 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -2626,6 +2626,9 @@ proc check_effective_target_floatn_nx_runtime {} { # the function name. proc add_options_for_float16 { flags } { + if { [istarget arm*-*-*] } { + return "$flags -mfp16-format=ieee" + } return "$flags" }