[nvptx] Add type arg to TARGET_LIBC_HAS_FUNCTION
authorTom de Vries <tdevries@suse.de>
Tue, 29 Sep 2020 08:10:06 +0000 (10:10 +0200)
committerTom de Vries <tdevries@suse.de>
Wed, 30 Sep 2020 12:36:56 +0000 (14:36 +0200)
GCC has a target hook TARGET_LIBC_HAS_FUNCTION, which tells the compiler
which functions it can expect to be present in libc.

The default target hook does not include the sincos functions.

The nvptx port of newlib does include sincos and sincosf, but not sincosl.

The target hook TARGET_LIBC_HAS_FUNCTION does not distinguish between sincos,
sincosf and sincosl, so if we enable it for the sincos functions, then for
test.c:
...
long double x, a, b;
int main (void) {
  x = 0.5;
  a = sinl (x);
  b = cosl (x);
  printf ("a: %f\n", (double)a);
  printf ("b: %f\n", (double)b);
  return 0;
}
...
we introduce a regression:
...
$ gcc test.c -lm -O2
unresolved symbol sincosl
collect2: error: ld returned 1 exit status
...

Add a type argument to target hook TARGET_LIBC_HAS_FUNCTION_TYPE, and use it
in nvptx_libc_has_function_type to enable sincos and sincosf, but not sincosl.

Build and reg-tested on x86_64-linux.

Build and tested on nvptx.

gcc/ChangeLog:

2020-09-28  Tobias Burnus  <tobias@codesourcery.com>
    Tom de Vries  <tdevries@suse.de>

* builtins.c (expand_builtin_cexpi, fold_builtin_sincos): Update
targetm.libc_has_function call.
* builtins.def (DEF_C94_BUILTIN, DEF_C99_BUILTIN, DEF_C11_BUILTIN):
(DEF_C2X_BUILTIN, DEF_C99_COMPL_BUILTIN, DEF_C99_C90RES_BUILTIN):
Same.
* config/darwin-protos.h (darwin_libc_has_function): Update prototype.
* config/darwin.c (darwin_libc_has_function): Add arg.
* config/linux-protos.h (linux_libc_has_function): Update prototype.
* config/linux.c (linux_libc_has_function): Add arg.
* config/i386/i386.c (ix86_libc_has_function): Update
targetm.libc_has_function call.
* config/nvptx/nvptx.c (nvptx_libc_has_function): New function.
(TARGET_LIBC_HAS_FUNCTION): Redefine to nvptx_libc_has_function.
* convert.c (convert_to_integer_1): Update targetm.libc_has_function
call.
* match.pd: Same.
* target.def (libc_has_function): Add arg.
* doc/tm.texi: Regenerate.
* targhooks.c (default_libc_has_function, gnu_libc_has_function)
(no_c99_libc_has_function): Add arg.
* targhooks.h (default_libc_has_function, no_c99_libc_has_function)
(gnu_libc_has_function): Update prototype.
* tree-ssa-math-opts.c (pass_cse_sincos::execute): Update
targetm.libc_has_function call.

gcc/fortran/ChangeLog:

2020-09-30  Tom de Vries  <tdevries@suse.de>

* f95-lang.c (gfc_init_builtin_functions):  Update
targetm.libc_has_function call.

16 files changed:
gcc/builtins.c
gcc/builtins.def
gcc/config/darwin-protos.h
gcc/config/darwin.c
gcc/config/i386/i386.c
gcc/config/linux-protos.h
gcc/config/linux.c
gcc/config/nvptx/nvptx.c
gcc/convert.c
gcc/doc/tm.texi
gcc/fortran/f95-lang.c
gcc/match.pd
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h
gcc/tree-ssa-math-opts.c

index cac842fd4a39c4a3c1817ae76edee64e0e7ad417..8f2662bb7284775a1cb44f8ff15fe80a60df2e05 100644 (file)
@@ -2733,7 +2733,7 @@ expand_builtin_cexpi (tree exp, rtx target)
       /* Compute into op1 and op2.  */
       expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
     }
-  else if (targetm.libc_has_function (function_sincos))
+  else if (targetm.libc_has_function (function_sincos, type))
     {
       tree call, fn = NULL_TREE;
       tree top1, top2;
@@ -9770,7 +9770,7 @@ fold_builtin_sincos (location_t loc,
     }
   if (!call)
     {
-      if (!targetm.libc_has_function (function_c99_math_complex)
+      if (!targetm.libc_has_function (function_c99_math_complex, type)
          || !builtin_decl_implicit_p (fn))
        return NULL_TREE;
       fndecl = builtin_decl_explicit (fn);
index 102322b79121ae0d221b531aaa76206523980367..95428c010d94ebddc74771af9c92afb119dc49b8 100644 (file)
@@ -138,34 +138,41 @@ along with GCC; see the file COPYING3.  If not see
 #undef DEF_C94_BUILTIN
 #define DEF_C94_BUILTIN(ENUM, NAME, TYPE, ATTRS)       \
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,   \
-              true, true, !flag_isoc94, ATTRS, targetm.libc_has_function (function_c94), true)
+              true, true, !flag_isoc94, ATTRS, \
+              targetm.libc_has_function (function_c94, NULL_TREE), true)
 
 /* Like DEF_LIB_BUILTIN, except that the function is only a part of
    the standard in C99 or above.  */
 #undef DEF_C99_BUILTIN
 #define DEF_C99_BUILTIN(ENUM, NAME, TYPE, ATTRS)       \
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,   \
-              true, true, !flag_isoc99, ATTRS, targetm.libc_has_function (function_c99_misc), true)
+              true, true, !flag_isoc99, ATTRS, \
+              targetm.libc_has_function (function_c99_misc, NULL_TREE), true)
 
 /* Like DEF_LIB_BUILTIN, except that the function is only a part of
    the standard in C11 or above.  */
 #undef DEF_C11_BUILTIN
 #define DEF_C11_BUILTIN(ENUM, NAME, TYPE, ATTRS)       \
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,   \
-              true, true, !flag_isoc11, ATTRS, targetm.libc_has_function (function_c11_misc), true)
+              true, true, !flag_isoc11, ATTRS, \
+              targetm.libc_has_function (function_c11_misc, NULL_TREE), true)
 
 /* Like DEF_LIB_BUILTIN, except that the function is only a part of
    the standard in C2x or above.  */
 #undef DEF_C2X_BUILTIN
 #define DEF_C2X_BUILTIN(ENUM, NAME, TYPE, ATTRS)       \
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,   \
-              true, true, !flag_isoc2x, ATTRS, targetm.libc_has_function (function_c2x_misc), true)
+              true, true, !flag_isoc2x, ATTRS, \
+              targetm.libc_has_function (function_c2x_misc, NULL_TREE), true)
 
 /* Like DEF_C99_BUILTIN, but for complex math functions.  */
 #undef DEF_C99_COMPL_BUILTIN
 #define DEF_C99_COMPL_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,   \
-              true, true, !flag_isoc99, ATTRS, targetm.libc_has_function (function_c99_math_complex), true)
+              true, true, !flag_isoc99, ATTRS, \
+              targetm.libc_has_function (function_c99_math_complex, \
+                                         NULL_TREE), \
+              true)
 
 /* Builtin that is specified by C99 and C90 reserve the name for future use.
    We can still recognize the builtin in C90 mode but we can't produce it
@@ -173,7 +180,8 @@ along with GCC; see the file COPYING3.  If not see
 #undef DEF_C99_C90RES_BUILTIN
 #define DEF_C99_C90RES_BUILTIN(ENUM, NAME, TYPE, ATTRS)        \
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,   \
-              true, true, !flag_isoc99, ATTRS, targetm.libc_has_function (function_c99_misc), true)
+              true, true, !flag_isoc99, ATTRS, \
+              targetm.libc_has_function (function_c99_misc, NULL_TREE), true)
 
 /* Builtin that C99 reserve the name for future use. We can still recognize
    the builtin in C99 mode but we can't produce it implicitly.  */
index 54cd1e4c1a447d1a17cd235f41621deb53fe337c..49c540fe08e4a6e632349e547afafc847e386ea4 100644 (file)
@@ -125,6 +125,6 @@ extern bool darwin_kextabi_p (void);
 extern void darwin_override_options (void);
 extern void darwin_patch_builtins (void);
 extern void darwin_rename_builtins (void);
-extern bool darwin_libc_has_function (enum function_class fn_class);
+extern bool darwin_libc_has_function (enum function_class fn_class, tree);
 
 #endif /* CONFIG_DARWIN_PROTOS_H */
index c8edfb88b59539d15f53efdee7b14d6b81e4dd24..b64aaa7b1a7b3caa61a9efcbff0e907170c3741a 100644 (file)
@@ -3542,7 +3542,8 @@ darwin_rename_builtins (void)
 }
 
 bool
-darwin_libc_has_function (enum function_class fn_class)
+darwin_libc_has_function (enum function_class fn_class,
+                         tree type ATTRIBUTE_UNUSED)
 {
   if (fn_class == function_sincos)
     return (strverscmp (darwin_macosx_version_min, "10.9") >= 0);
index c890a73329398eb4fdb02db1184651932c893356..f684954af8121a34703d4ce556b97d95428ac04d 100644 (file)
@@ -1484,7 +1484,7 @@ ix86_reg_parm_stack_space (const_tree fndecl)
 bool
 ix86_libc_has_function (enum function_class fn_class)
 {
-  return targetm.libc_has_function (fn_class);
+  return targetm.libc_has_function (fn_class, NULL_TREE);
 }
 
 /* Returns value SYSV_ABI, MS_ABI dependent on fntype,
index 3759187f1ab78530d418c0f2f885a0fc290856fe..c52778b4b35b2db5c5fe5631b19ed164fc4f1294 100644 (file)
@@ -19,4 +19,4 @@ along with GCC; see the file COPYING3.  If not see
 
 extern bool linux_has_ifunc_p (void);
 
-extern bool linux_libc_has_function (enum function_class fn_class);
+extern bool linux_libc_has_function (enum function_class fn_class, tree);
index 98761536cf07bc5247c04567daf4008bea4e96e9..83ffff43f8b1bd34a1986a16e7ea3567e1ef1215 100644 (file)
@@ -25,7 +25,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "linux-protos.h"
 
 bool
-linux_libc_has_function (enum function_class fn_class)
+linux_libc_has_function (enum function_class fn_class,
+                        tree type ATTRIBUTE_UNUSED)
 {
   if (OPTION_GLIBC || OPTION_MUSL)
     return true;
index de82f9ab875193e14d6a21454c5b002a7cc48849..afac1bda45d25db48e15368905d044e1fbc0f45a 100644 (file)
@@ -6536,6 +6536,23 @@ nvptx_set_current_function (tree fndecl)
   oacc_bcast_partition = 0;
 }
 
+/* Implement TARGET_LIBC_HAS_FUNCTION.  */
+
+bool
+nvptx_libc_has_function (enum function_class fn_class, tree type)
+{
+  if (fn_class == function_sincos)
+    {
+      if (type != NULL_TREE)
+       /* Currently, newlib does not support sincosl.  */
+       return type == float_type_node || type == double_type_node;
+      else
+       return true;
+    }
+
+  return default_libc_has_function (fn_class, type);
+}
+
 #undef TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE nvptx_option_override
 
@@ -6681,6 +6698,9 @@ nvptx_set_current_function (tree fndecl)
 #undef TARGET_SET_CURRENT_FUNCTION
 #define TARGET_SET_CURRENT_FUNCTION nvptx_set_current_function
 
+#undef TARGET_LIBC_HAS_FUNCTION
+#define TARGET_LIBC_HAS_FUNCTION nvptx_libc_has_function
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-nvptx.h"
index 292c5133974ac9242d76a083b8dfd7ba85f78edd..7b28332584c8dd215ae727d96e9c0ed6f3d7f7d3 100644 (file)
@@ -501,7 +501,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
        CASE_FLT_FN (BUILT_IN_CEIL):
        CASE_FLT_FN_FLOATN_NX (BUILT_IN_CEIL):
          /* Only convert in ISO C99 mode.  */
-         if (!targetm.libc_has_function (function_c99_misc))
+         if (!targetm.libc_has_function (function_c99_misc, intype))
            break;
          if (outprec < TYPE_PRECISION (integer_type_node)
              || (outprec == TYPE_PRECISION (integer_type_node)
@@ -518,7 +518,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
        CASE_FLT_FN (BUILT_IN_FLOOR):
        CASE_FLT_FN_FLOATN_NX (BUILT_IN_FLOOR):
          /* Only convert in ISO C99 mode.  */
-         if (!targetm.libc_has_function (function_c99_misc))
+         if (!targetm.libc_has_function (function_c99_misc, intype))
            break;
          if (outprec < TYPE_PRECISION (integer_type_node)
              || (outprec == TYPE_PRECISION (integer_type_node)
@@ -535,7 +535,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
        CASE_FLT_FN (BUILT_IN_ROUND):
        CASE_FLT_FN_FLOATN_NX (BUILT_IN_ROUND):
          /* Only convert in ISO C99 mode and with -fno-math-errno.  */
-         if (!targetm.libc_has_function (function_c99_misc)
+         if (!targetm.libc_has_function (function_c99_misc, intype)
              || flag_errno_math)
            break;
          if (outprec < TYPE_PRECISION (integer_type_node)
@@ -559,7 +559,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
        CASE_FLT_FN (BUILT_IN_RINT):
        CASE_FLT_FN_FLOATN_NX (BUILT_IN_RINT):
          /* Only convert in ISO C99 mode and with -fno-math-errno.  */
-         if (!targetm.libc_has_function (function_c99_misc)
+         if (!targetm.libc_has_function (function_c99_misc, intype)
              || flag_errno_math)
            break;
          if (outprec < TYPE_PRECISION (integer_type_node)
index 8e9e7701531534bd2444c62d4af88291da58e5f8..97437e8274fdf17b4e9c3b4b1d19fc6012fae704 100644 (file)
@@ -5602,9 +5602,12 @@ refers to the global ``variable'' @code{errno}.  (On certain systems,
 macro, a reasonable default is used.
 @end defmac
 
-@deftypefn {Target Hook} bool TARGET_LIBC_HAS_FUNCTION (enum function_class @var{fn_class})
+@deftypefn {Target Hook} bool TARGET_LIBC_HAS_FUNCTION (enum function_class @var{fn_class}, tree @var{type})
 This hook determines whether a function from a class of functions
-@var{fn_class} is present in the target C library.
+@var{fn_class} is present in the target C library.  If @var{type} is NULL,
+the caller asks for support for all standard (float, double, long double)
+types.  If @var{type} is non-NULL, the caller asks for support for a
+specific type.
 @end deftypefn
 
 @deftypefn {Target Hook} bool TARGET_LIBC_HAS_FAST_FUNCTION (int @var{fcode})
index e3288d7f576eaa89f20d69251ef4b3bb1916f742..526b7219e4bd835fcfa8de14d672e72f592ad5bb 100644 (file)
@@ -881,7 +881,7 @@ gfc_init_builtin_functions (void)
                      BUILT_IN_POWIF, "powif", ATTR_CONST_NOTHROW_LEAF_LIST);
 
 
-  if (targetm.libc_has_function (function_c99_math_complex))
+  if (targetm.libc_has_function (function_c99_math_complex, NULL_TREE))
     {
       gfc_define_builtin ("__builtin_cbrtl", mfunc_longdouble[0],
                          BUILT_IN_CBRTL, "cbrtl",
@@ -903,7 +903,7 @@ gfc_init_builtin_functions (void)
                          ATTR_CONST_NOTHROW_LEAF_LIST);
     }
 
-  if (targetm.libc_has_function (function_sincos))
+  if (targetm.libc_has_function (function_sincos, NULL_TREE))
     {
       gfc_define_builtin ("__builtin_sincosl",
                          func_longdouble_longdoublep_longdoublep,
index e6dcdd0b855881c49f4eb7e4640a5421ea0480aa..952643f3c6d7a33a4631819991c7651f511ac8d3 100644 (file)
@@ -5185,7 +5185,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (with {
        const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (@0);
        bool use_exp2 = false;
-       if (targetm.libc_has_function (function_c99_misc)
+       if (targetm.libc_has_function (function_c99_misc, TREE_TYPE (@0))
           && value->cl == rvc_normal)
         {
           REAL_VALUE_TYPE frac_rvt = *value;
@@ -5484,7 +5484,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       cexpis (CEXPI)
   (simplify
    (cexps compositional_complex@0)
-   (if (targetm.libc_has_function (function_c99_math_complex))
+   (if (targetm.libc_has_function (function_c99_math_complex, TREE_TYPE (@0)))
     (complex
      (mult (exps@1 (realpart @0)) (realpart (cexpis:type@2 (imagpart @0))))
      (mult @1 (imagpart @2)))))))
@@ -5536,7 +5536,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  /* truncl(extend(x)) and trunc(extend(x)) -> extend(truncf(x)), etc.,
     if x is a float.  */
  (if (optimize && canonicalize_math_p ()
-      && targetm.libc_has_function (function_c99_misc))
+      && targetm.libc_has_function (function_c99_misc, NULL_TREE))
   (simplify
    (froms (convert float_value_p@0))
    (convert (tos @0)))))
index fc4563d144cd5fb573e27f397c379c5438563d9e..ed2da154e30fd0b06dd01f33b3370daf9a909b80 100644 (file)
@@ -2618,8 +2618,11 @@ set via @code{__attribute__}.",
 DEFHOOK
 (libc_has_function,
  "This hook determines whether a function from a class of functions\n\
-@var{fn_class} is present in the target C library.",
- bool, (enum function_class fn_class),
+@var{fn_class} is present in the target C library.  If @var{type} is NULL,\n\
+the caller asks for support for all standard (float, double, long double)\n\
+types.  If @var{type} is non-NULL, the caller asks for support for a\n\
+specific type.",
+ bool, (enum function_class fn_class, tree type),
  default_libc_has_function)
 
 DEFHOOK
index da4805d284e53247d57764988a75613828d6bee7..5d94fce2282bbb2b2e0b36475f4ad073ad0f7c09 100644 (file)
@@ -1641,7 +1641,8 @@ default_have_conditional_execution (void)
 /* By default we assume that c99 functions are present at the runtime,
    but sincos is not.  */
 bool
-default_libc_has_function (enum function_class fn_class)
+default_libc_has_function (enum function_class fn_class,
+                          tree type ATTRIBUTE_UNUSED)
 {
   if (fn_class == function_c94
       || fn_class == function_c99_misc
@@ -1660,13 +1661,15 @@ default_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED)
 }
 
 bool
-gnu_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
+gnu_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED,
+                      tree type ATTRIBUTE_UNUSED)
 {
   return true;
 }
 
 bool
-no_c99_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
+no_c99_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED,
+                         tree type ATTRIBUTE_UNUSED)
 {
   return false;
 }
index b572a36e8cf0147714fd14ec9096198c7d4e1a6d..44ab9262c2adeba9a57ee4bde027a8b79f0d7238 100644 (file)
@@ -208,10 +208,10 @@ extern rtx default_addr_space_convert (rtx, tree, tree);
 extern unsigned int default_case_values_threshold (void);
 extern bool default_have_conditional_execution (void);
 
-extern bool default_libc_has_function (enum function_class);
+extern bool default_libc_has_function (enum function_class, tree);
 extern bool default_libc_has_fast_function (int fcode);
-extern bool no_c99_libc_has_function (enum function_class);
-extern bool gnu_libc_has_function (enum function_class);
+extern bool no_c99_libc_has_function (enum function_class, tree);
+extern bool gnu_libc_has_function (enum function_class, tree);
 
 extern tree default_builtin_tm_load_store (tree);
 
index 8423caa3ee3c2e88c6321d637bdc92044a942102..bdbb9d965f09ea60be04ae5d07589aba1bc59b93 100644 (file)
@@ -2176,12 +2176,14 @@ pass_cse_sincos::execute (function *fun)
                CASE_CFN_COS:
                CASE_CFN_SIN:
                CASE_CFN_CEXPI:
+                 arg = gimple_call_arg (stmt, 0);
                  /* Make sure we have either sincos or cexp.  */
-                 if (!targetm.libc_has_function (function_c99_math_complex)
-                     && !targetm.libc_has_function (function_sincos))
+                 if (!targetm.libc_has_function (function_c99_math_complex,
+                                                 TREE_TYPE (arg))
+                     && !targetm.libc_has_function (function_sincos,
+                                                    TREE_TYPE (arg)))
                    break;
 
-                 arg = gimple_call_arg (stmt, 0);
                  if (TREE_CODE (arg) == SSA_NAME)
                    cfg_changed |= execute_cse_sincos_1 (arg);
                  break;