[Patch ARM 17/17] Enable _Float16 for ARM and fix PR target/63250
authorJames Greenhalgh <james.greenhalgh@arm.com>
Wed, 23 Nov 2016 17:36:21 +0000 (17:36 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Wed, 23 Nov 2016 17:36:21 +0000 (17:36 +0000)
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

gcc/ChangeLog
gcc/config/arm/arm-builtins.c
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/testsuite/ChangeLog
gcc/testsuite/lib/target-supports.exp

index 4ab87a9d009ca0876881b4f4f459393db9a8fe57..600a9ef747ae24769e3e8de573f973945a2010f3 100644 (file)
@@ -1,3 +1,19 @@
+2016-11-23  James Greenhalgh  <james.greenhalgh@arm.com>
+
+       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  <james.greenhalgh@arm.com>
 
        * config/arm/arm.c (arm_convert_to_type): Delete.
index e73043db6db69fa64bb1e72cf71a36d7169062db..5ed38d1608cfbfbd1248d76705fcf675bc36c2b2 100644 (file)
@@ -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");
 }
 
index 118b93b94308a1e2411d330faaeff8c873b39264..74cb64ce7892244bca5bb4a73631e67cd67ed285 100644 (file)
@@ -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);
 \f
 /* 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;
 \f
 /* 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.
 
index 15930f0ca8fa148f1b02745574cc6994f0c5f837..464710b2a98ee737810816ac50aca77e5610e7fa 100644 (file)
@@ -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;
+
 \f
 #undef  CPP_SPEC
 #define CPP_SPEC "%(subtarget_cpp_spec)                                        \
index 0d5909052d44c00c92cad6186c4fc132d81cc120..0b5c305921473c5970d017320ed33d985bc24687 100644 (file)
@@ -1,3 +1,9 @@
+2016-11-23  James Greenhalgh  <james.greenhalgh@arm.com>
+
+       PR target/63250
+       * lib/target-supports.exp (add_options_for_float16): Add
+       -mfp16-format=ieee when testign arm*-*-*.
+
 2016-11-23  James Greenhalgh  <james.greenhalgh@arm.com>
 
        * gcc.target/arm/fp16-rounding-alt-1.c (ROUNDED): Change expected
index 624c2e29f7c50904c9cd58d322a60894b2c60c60..2192eb6539b12896816f8844e056f3bf5016e4d9 100644 (file)
@@ -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"
 }