On Wed, 6 Apr 2022, Jakub Jelinek wrote:

> On Wed, Apr 06, 2022 at 09:49:25AM +0200, Richard Biener wrote:
> > On trees we'd use tree_[sign_]nop_conversion () instead of
> > useless_type_conversion_p, I think it's OK to allow all such
> > pointer conversions.  In the end this probably means being
> > more forgiving than TYPE_MAIN_VARIANT equivalence throughout, that
> > would also make the code more similar to 
> > gimple_builtin_call_types_compatible_p besides
> > s/useless_type_conversion_p/tree_sign_nop_conversion/
> 
> Here is an updated patch to do that, allow differences in pointer types
> and tweak the promotion handling.
> There is no tree_sign_nop_conversion_p, so I've used
> tree_nop_conversion_p.  What tree_sign_nop_conversion does on top of
> that is just that it verifies both types are pointer types or
> neither is and in the latter case TYPE_UNSIGNED is the same.
> So the patch verifies both are POINTER_TYPE_P for the one case
> and for the promotion where it already checks the unpromoted type
> is integral checks if promoted one is integral too and signed.
> 
> I've also changed the patch to match the now committed gimple.cc
> change where the builtin_decl_explicit is inside of the
> *_call_types_compatible_p function instead of the caller.
> 
> Bootstrapped/regtested on powerpc64le-linux, ok for trunk?

OK.

Thanks,
Richard.

> 2022-04-06  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR tree-optimization/105150
>       * tree.cc (tree_builtin_call_types_compatible_p): New function.
>       (get_call_combined_fn): Use it.
> 
>       * gcc.dg/pr105150.c: New test.
> 
> --- gcc/tree.cc.jj    2022-04-06 09:59:03.312066863 +0200
> +++ gcc/tree.cc       2022-04-06 10:52:55.176755024 +0200
> @@ -8406,6 +8406,59 @@ get_callee_fndecl (const_tree call)
>    return NULL_TREE;
>  }
>  
> +/* Return true when STMTs arguments and return value match those of FNDECL,
> +   a decl of a builtin function.  */
> +
> +static bool
> +tree_builtin_call_types_compatible_p (const_tree call, tree fndecl)
> +{
> +  gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN);
> +
> +  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
> +    if (tree decl = builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl)))
> +      fndecl = decl;
> +
> +  if (TYPE_MAIN_VARIANT (TREE_TYPE (call))
> +      != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))))
> +    return false;
> +
> +  tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
> +  unsigned nargs = call_expr_nargs (call);
> +  for (unsigned i = 0; i < nargs; ++i, targs = TREE_CHAIN (targs))
> +    {
> +      /* Variadic args follow.  */
> +      if (!targs)
> +     return true;
> +      tree arg = CALL_EXPR_ARG (call, i);
> +      tree type = TREE_VALUE (targs);
> +      if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (TREE_TYPE (arg)))
> +     {
> +       /* For pointer arguments be more forgiving, e.g. due to
> +          FILE * vs. fileptr_type_node, or say char * vs. const char *
> +          differences etc.  */
> +       if (POINTER_TYPE_P (type)
> +           && POINTER_TYPE_P (TREE_TYPE (arg))
> +           && tree_nop_conversion_p (type, TREE_TYPE (arg)))
> +         continue;
> +       /* char/short integral arguments are promoted to int
> +          by several frontends if targetm.calls.promote_prototypes
> +          is true.  Allow such promotion too.  */
> +       if (INTEGRAL_TYPE_P (type)
> +           && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
> +           && INTEGRAL_TYPE_P (TREE_TYPE (arg))
> +           && !TYPE_UNSIGNED (TREE_TYPE (arg))
> +           && targetm.calls.promote_prototypes (TREE_TYPE (fndecl))
> +           && tree_nop_conversion_p (integer_type_node,
> +                                     TREE_TYPE (arg)))
> +         continue;
> +       return false;
> +     }
> +    }
> +  if (targs && !VOID_TYPE_P (TREE_VALUE (targs)))
> +    return false;
> +  return true;
> +}
> +
>  /* If CALL_EXPR CALL calls a normal built-in function or an internal 
> function,
>     return the associated function code, otherwise return CFN_LAST.  */
>  
> @@ -8419,7 +8472,9 @@ get_call_combined_fn (const_tree call)
>      return as_combined_fn (CALL_EXPR_IFN (call));
>  
>    tree fndecl = get_callee_fndecl (call);
> -  if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
> +  if (fndecl
> +      && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
> +      && tree_builtin_call_types_compatible_p (call, fndecl))
>      return as_combined_fn (DECL_FUNCTION_CODE (fndecl));
>  
>    return CFN_LAST;
> --- gcc/testsuite/gcc.dg/pr105150.c.jj        2022-04-06 10:51:12.801191206 
> +0200
> +++ gcc/testsuite/gcc.dg/pr105150.c   2022-04-06 10:51:12.801191206 +0200
> @@ -0,0 +1,8 @@
> +/* PR tree-optimization/105150 */
> +/* { dg-options "-w -Ofast" } */
> +
> +#define A(name) __typeof (__builtin_##name (0)) name (); \
> +  float name##1 () { return !name (1); } \
> +  double name##2 () { return name (1.0L); }
> +#define B(name) A(name) A(name##l)
> +B (sqrt)
> 
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)

Reply via email to