On Wed, Oct 7, 2020 at 7:15 PM Alexandre Oliva <ol...@adacore.com> wrote:
>
> On Oct  6, 2020, Richard Biener <richard.guent...@gmail.com> wrote:
>
> > So how about that mathfn_type helper instead of hard-wring this logic
> > in sincos()?
>
> Like this?
>
> Regstrapped on x86_64-linux-gnu.  Ok to install?

OK with a minor nit, see below

> I'm a little unhappy with the duplication of the CASE_MATHFN* sequence,
> that ought to be kept in sync, , and considered turning that whole
> sequence into a #define used in both places, but that would bloat the
> patch further and make it less readable, so I figured I'd propose this
> one first.  Please let me know if you agree this additional change would
> make it better.

Yeah, I guess so.

> take type from intrinsic in sincos pass
>
> From: Alexandre Oliva <ol...@adacore.com>
>
> This is a first step towards enabling the sincos optimization in Ada.
>
> The issue this patch solves is that sincos takes the type to be looked
> up with mathfn_built_in from variables or temporaries passed as
> arguments to SIN and COS intrinsics.  In Ada, different float types
> may be used but, despite their representation equivalence, their
> distinctness causes the optimization to be skipped, because they are
> not the types that mathfn_built_in expects.
>
> This patch introduces a function that maps intrinsics to the type
> they're associated with, and uses that type, obtained from the
> intrinsics used in calls to be optimized, to look up the correspoding
> CEXPI intrinsic.
>
> For the sake of defensive programming, when using the type obtained
> from the intrinsic, it now checks that, if different types are found
> for the used argument, or for other calls that use it, that the types
> are interchangeable.
>
>
> for  gcc/ChangeLog
>
>         * builtins.c (mathfn_built_in_type): New.
>         * builtins.h (mathfn_built_in_type): Declare.
>         * tree-ssa-math-opts.c (execute_cse_sincos_1): Use it to
>         obtain the type expected by the intrinsic.
> ---
>  gcc/builtins.c           |  147 
> ++++++++++++++++++++++++++++++++++++++++++++++
>  gcc/builtins.h           |    1
>  gcc/tree-ssa-math-opts.c |   17 ++++-
>  3 files changed, 162 insertions(+), 3 deletions(-)
>
> diff --git a/gcc/builtins.c b/gcc/builtins.c
> index f91266e4..5649242 100644
> --- a/gcc/builtins.c
> +++ b/gcc/builtins.c
> @@ -2160,6 +2160,7 @@ mathfn_built_in_2 (tree type, combined_fn fn)
>
>    switch (fn)
>      {
> +      /* Copied to mathfn_built_in_type, please keep in sync.  */
>      CASE_MATHFN (ACOS)
>      CASE_MATHFN (ACOSH)
>      CASE_MATHFN (ASIN)
> @@ -2278,6 +2279,10 @@ mathfn_built_in_2 (tree type, combined_fn fn)
>      return END_BUILTINS;
>  }
>
> +#undef CASE_MATHFN
> +#undef CASE_MATHFN_FLOATN
> +#undef CASE_MATHFN_REENT
> +
>  /* Return mathematic function equivalent to FN but operating directly on 
> TYPE,
>     if available.  If IMPLICIT_P is true use the implicit builtin declaration,
>     otherwise use the explicit declaration.  If we can't do the conversion,
> @@ -2313,6 +2318,148 @@ mathfn_built_in (tree type, enum built_in_function fn)
>    return mathfn_built_in_1 (type, as_combined_fn (fn), /*implicit=*/ 1);
>  }
>
> +/* Return the type associated with a built in function, i.e., the one
> +   to be passed to mathfn_built_in to get the type-specific
> +   function.  */
> +
> +tree
> +mathfn_built_in_type (combined_fn fn)
> +{
> +#define CASE_MATHFN(MATHFN)                    \
> +  case BUILT_IN_##MATHFN:                      \
> +    return double_type_node;                   \
> +  case BUILT_IN_##MATHFN##F:                   \
> +    return float_type_node;                    \
> +  case BUILT_IN_##MATHFN##L:                   \
> +    return long_double_type_node;
> +
> +#define CASE_MATHFN_FLOATN(MATHFN)             \
> +  CASE_MATHFN(MATHFN)                          \
> +  case BUILT_IN_##MATHFN##F16:                 \
> +    return float16_type_node;                  \
> +  case BUILT_IN_##MATHFN##F32:                 \
> +    return float32_type_node;                  \
> +  case BUILT_IN_##MATHFN##F64:                 \
> +    return float64_type_node;                  \
> +  case BUILT_IN_##MATHFN##F128:                        \
> +    return float128_type_node;                 \
> +  case BUILT_IN_##MATHFN##F32X:                        \
> +    return float32x_type_node;                 \
> +  case BUILT_IN_##MATHFN##F64X:                        \
> +    return float64x_type_node;                 \
> +  case BUILT_IN_##MATHFN##F128X:               \
> +    return float128x_type_node;
> +
> +/* Similar to above, but appends _R after any F/L suffix.  */
> +#define CASE_MATHFN_REENT(MATHFN) \
> +  case BUILT_IN_##MATHFN##_R:                  \
> +    return double_type_node;                   \
> +  case BUILT_IN_##MATHFN##F_R:                 \
> +    return float_type_node;                    \
> +  case BUILT_IN_##MATHFN##L_R:                 \
> +    return long_double_type_node;
> +
> +  switch (fn)
> +    {
> +      /* Copied from mathfn_built_in_2, please keep in sync.  */
> +    CASE_MATHFN (ACOS)
> +    CASE_MATHFN (ACOSH)
> +    CASE_MATHFN (ASIN)
> +    CASE_MATHFN (ASINH)
> +    CASE_MATHFN (ATAN)
> +    CASE_MATHFN (ATAN2)
> +    CASE_MATHFN (ATANH)
> +    CASE_MATHFN (CBRT)
> +    CASE_MATHFN_FLOATN (CEIL)
> +    CASE_MATHFN (CEXPI)
> +    CASE_MATHFN_FLOATN (COPYSIGN)
> +    CASE_MATHFN (COS)
> +    CASE_MATHFN (COSH)
> +    CASE_MATHFN (DREM)
> +    CASE_MATHFN (ERF)
> +    CASE_MATHFN (ERFC)
> +    CASE_MATHFN (EXP)
> +    CASE_MATHFN (EXP10)
> +    CASE_MATHFN (EXP2)
> +    CASE_MATHFN (EXPM1)
> +    CASE_MATHFN (FABS)
> +    CASE_MATHFN (FDIM)
> +    CASE_MATHFN_FLOATN (FLOOR)
> +    CASE_MATHFN_FLOATN (FMA)
> +    CASE_MATHFN_FLOATN (FMAX)
> +    CASE_MATHFN_FLOATN (FMIN)
> +    CASE_MATHFN (FMOD)
> +    CASE_MATHFN (FREXP)
> +    CASE_MATHFN (GAMMA)
> +    CASE_MATHFN_REENT (GAMMA) /* GAMMA_R */
> +    CASE_MATHFN (HUGE_VAL)
> +    CASE_MATHFN (HYPOT)
> +    CASE_MATHFN (ILOGB)
> +    CASE_MATHFN (ICEIL)
> +    CASE_MATHFN (IFLOOR)
> +    CASE_MATHFN (INF)
> +    CASE_MATHFN (IRINT)
> +    CASE_MATHFN (IROUND)
> +    CASE_MATHFN (ISINF)
> +    CASE_MATHFN (J0)
> +    CASE_MATHFN (J1)
> +    CASE_MATHFN (JN)
> +    CASE_MATHFN (LCEIL)
> +    CASE_MATHFN (LDEXP)
> +    CASE_MATHFN (LFLOOR)
> +    CASE_MATHFN (LGAMMA)
> +    CASE_MATHFN_REENT (LGAMMA) /* LGAMMA_R */
> +    CASE_MATHFN (LLCEIL)
> +    CASE_MATHFN (LLFLOOR)
> +    CASE_MATHFN (LLRINT)
> +    CASE_MATHFN (LLROUND)
> +    CASE_MATHFN (LOG)
> +    CASE_MATHFN (LOG10)
> +    CASE_MATHFN (LOG1P)
> +    CASE_MATHFN (LOG2)
> +    CASE_MATHFN (LOGB)
> +    CASE_MATHFN (LRINT)
> +    CASE_MATHFN (LROUND)
> +    CASE_MATHFN (MODF)
> +    CASE_MATHFN (NAN)
> +    CASE_MATHFN (NANS)
> +    CASE_MATHFN_FLOATN (NEARBYINT)
> +    CASE_MATHFN (NEXTAFTER)
> +    CASE_MATHFN (NEXTTOWARD)
> +    CASE_MATHFN (POW)
> +    CASE_MATHFN (POWI)
> +    CASE_MATHFN (POW10)
> +    CASE_MATHFN (REMAINDER)
> +    CASE_MATHFN (REMQUO)
> +    CASE_MATHFN_FLOATN (RINT)
> +    CASE_MATHFN_FLOATN (ROUND)
> +    CASE_MATHFN_FLOATN (ROUNDEVEN)
> +    CASE_MATHFN (SCALB)
> +    CASE_MATHFN (SCALBLN)
> +    CASE_MATHFN (SCALBN)
> +    CASE_MATHFN (SIGNBIT)
> +    CASE_MATHFN (SIGNIFICAND)
> +    CASE_MATHFN (SIN)
> +    CASE_MATHFN (SINCOS)
> +    CASE_MATHFN (SINH)
> +    CASE_MATHFN_FLOATN (SQRT)
> +    CASE_MATHFN (TAN)
> +    CASE_MATHFN (TANH)
> +    CASE_MATHFN (TGAMMA)
> +    CASE_MATHFN_FLOATN (TRUNC)
> +    CASE_MATHFN (Y0)
> +    CASE_MATHFN (Y1)
> +    CASE_MATHFN (YN)
> +
> +    default:
> +      return NULL_TREE;
> +    }
> +
> +#undef CASE_MATHFN
> +#undef CASE_MATHFN_FLOATN
> +#undef CASE_MATHFN_REENT
> +}
> +
>  /* If BUILT_IN_NORMAL function FNDECL has an associated internal function,
>     return its code, otherwise return IFN_LAST.  Note that this function
>     only tests whether the function is defined in internals.def, not whether
> diff --git a/gcc/builtins.h b/gcc/builtins.h
> index 504c618..72012a2 100644
> --- a/gcc/builtins.h
> +++ b/gcc/builtins.h
> @@ -109,6 +109,7 @@ extern void expand_builtin_setjmp_receiver (rtx);
>  extern void expand_builtin_update_setjmp_buf (rtx);
>  extern tree mathfn_built_in (tree, enum built_in_function fn);
>  extern tree mathfn_built_in (tree, combined_fn);
> +extern tree mathfn_built_in_type (combined_fn);
>  extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, scalar_int_mode);
>  extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, scalar_int_mode);
>  extern rtx expand_builtin_saveregs (void);
> diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
> index 4927255..7504569 100644
> --- a/gcc/tree-ssa-math-opts.c
> +++ b/gcc/tree-ssa-math-opts.c
> @@ -1139,7 +1139,7 @@ execute_cse_sincos_1 (tree name)
>  {
>    gimple_stmt_iterator gsi;
>    imm_use_iterator use_iter;
> -  tree fndecl, res, type;
> +  tree fndecl, res, type = NULL_TREE;
>    gimple *def_stmt, *use_stmt, *stmt;
>    int seen_cos = 0, seen_sin = 0, seen_cexpi = 0;
>    auto_vec<gimple *> stmts;
> @@ -1147,7 +1147,6 @@ execute_cse_sincos_1 (tree name)
>    int i;
>    bool cfg_changed = false;
>
> -  type = TREE_TYPE (name);
>    FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, name)
>      {
>        if (gimple_code (use_stmt) != GIMPLE_CALL
> @@ -1169,9 +1168,21 @@ execute_cse_sincos_1 (tree name)
>           break;
>
>         default:;
> +         continue;
>         }
> -    }
>
> +      tree t = mathfn_built_in_type (gimple_call_combined_fn (use_stmt));
> +      if (!type)
> +       {
> +         type = t;
> +         t = TREE_TYPE (name);
> +       }
> +      /* This checks that NAME has the right type in the first round,
> +        and, in subsequent rounds, that the built_in type is the same
> +        type.  */
> +      if (type != t && !tree_nop_conversion_p (type, t))

use !types_compatible_p (type, t) here if we don't want to go
with the stricter type == t (both yours and types_compatible_p
would treat long double and double the same in case they
are mapped to the same FP mode).  types_compatible_p
is the appropriate GIMPLE predicate here.

Thanks,
Richard.

> +       return false;
> +    }
>    if (seen_cos + seen_sin + seen_cexpi <= 1)
>      return false;
>
>
>
>
> --
> Alexandre Oliva, happy hacker
> https://FSFLA.org/blogs/lxo/
> Free Software Activist
> GNU Toolchain Engineer

Reply via email to