On Thu, Aug 7, 2025 at 4:55 AM Wilco Dijkstra <wilco.dijks...@arm.com> wrote:
>
>
> Add an optab for isnan.  This requires changes to the existing folding code
> to extend the interclass_mathfn infrastructure to support BUILT_IN_ISNAN.
> It now checks for a valid optab before emitting the generic expansion.
> There is no change if no optab is defined.  Update documentation, including
> the missing isinf entry.

Note the bug report for the missing optab documentation is PR 101852;
Some the script I added there; missed isinf.

Thanks,
Andrew

>
> Passes regress, OK for commit?
>
> gcc:
>         * builtins.cc (interclass_mathfn_icode): Add support for isnan
>         optab.
>         (expand_builtin): Add BUILT_IN_ISNAN to expand isnan optab.
>         (fold_builtin_interclass_mathfn): Expand BUILT_IN_ISNAN only after
>         checking for a valid optab.
>         (fold_builtin_classify): Move generic BUILT_IN_ISNAN expansion
>         to fold_builtin_interclass_mathfn.
>         (fold_builtin_1): For BUILT_IN_ISNAN first try fold_builtin_classify,
>         then fold_builtin_interclass_mathfn.
>         * optabs.def: Add isnan optab.
>         * doc/md.texi: Document isnan and isinf optabs.
>
> ---
>
> diff --git a/gcc/builtins.cc b/gcc/builtins.cc
> index 
> 7f580a3145ff5580f94d5493bfaab76e8cebeae4..3d21a8767c5d34f65c886723cb690f4889d46320
>  100644
> --- a/gcc/builtins.cc
> +++ b/gcc/builtins.cc
> @@ -2497,15 +2497,21 @@ interclass_mathfn_icode (tree arg, tree fndecl)
>    switch (DECL_FUNCTION_CODE (fndecl))
>      {
>      CASE_FLT_FN (BUILT_IN_ILOGB):
> -      errno_set = true; builtin_optab = ilogb_optab; break;
> +      errno_set = true;
> +      builtin_optab = ilogb_optab;
> +      break;
>      CASE_FLT_FN (BUILT_IN_ISINF):
> -      builtin_optab = isinf_optab; break;
> +      builtin_optab = isinf_optab;
> +      break;
>      case BUILT_IN_ISFINITE:
>        builtin_optab = isfinite_optab;
>        break;
>      case BUILT_IN_ISNORMAL:
>        builtin_optab = isnormal_optab;
>        break;
> +    CASE_FLT_FN (BUILT_IN_ISNAN):
> +      builtin_optab = isnan_optab;
> +      break;
>      CASE_FLT_FN (BUILT_IN_FINITE):
>      case BUILT_IN_FINITED32:
>      case BUILT_IN_FINITED64:
> @@ -2513,6 +2519,9 @@ interclass_mathfn_icode (tree arg, tree fndecl)
>      case BUILT_IN_ISINFD32:
>      case BUILT_IN_ISINFD64:
>      case BUILT_IN_ISINFD128:
> +    case BUILT_IN_ISNAND32:
> +    case BUILT_IN_ISNAND64:
> +    case BUILT_IN_ISNAND128:
>        /* These builtins have no optabs (yet).  */
>        break;
>      default:
> @@ -7959,6 +7968,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, 
> machine_mode mode,
>        gcc_fallthrough ();
>      CASE_FLT_FN (BUILT_IN_ISINF):
>      CASE_FLT_FN (BUILT_IN_FINITE):
> +    CASE_FLT_FN (BUILT_IN_ISNAN):
>      case BUILT_IN_ISFINITE:
>      case BUILT_IN_ISNORMAL:
>        target = expand_builtin_interclass_mathfn (exp, target);
> @@ -9832,6 +9842,19 @@ fold_builtin_interclass_mathfn (location_t loc, tree 
> fndecl, tree arg)
>                               max_exp, min_exp);
>         return result;
>        }
> +    CASE_FLT_FN (BUILT_IN_ISNAN):
> +    case BUILT_IN_ISNAND32:
> +    case BUILT_IN_ISNAND64:
> +    case BUILT_IN_ISNAND128:
> +      {
> +       /* In IBM extended NaN and Inf are encoded in the high-order double
> +          value only.  The low-order value is not significant.  */
> +       if (is_ibm_extended)
> +         arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
> +       arg = builtin_save_expr (arg);
> +       tree type = TREE_TYPE (TREE_TYPE (fndecl));
> +       return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
> +      }
>      default:
>        break;
>      }
> @@ -9903,18 +9926,7 @@ fold_builtin_classify (location_t loc, tree fndecl, 
> tree arg, int builtin_index)
>         return omit_one_operand_loc (loc, type, integer_one_node, arg);
>        if (!tree_expr_maybe_nan_p (arg))
>         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
> -
> -      {
> -       bool is_ibm_extended = MODE_COMPOSITE_P (TYPE_MODE (TREE_TYPE (arg)));
> -       if (is_ibm_extended)
> -         {
> -           /* NaN and Inf are encoded in the high-order double value
> -              only.  The low-order value is not significant.  */
> -           arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
> -         }
> -      }
> -      arg = builtin_save_expr (arg);
> -      return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
> +      return NULL_TREE;
>
>      case BUILT_IN_ISSIGNALING:
>        /* Folding to true for REAL_CST is done in fold_const_call_ss.
> @@ -10746,7 +10758,12 @@ fold_builtin_1 (location_t loc, tree expr, tree 
> fndecl, tree arg0)
>      case BUILT_IN_ISNAND32:
>      case BUILT_IN_ISNAND64:
>      case BUILT_IN_ISNAND128:
> -      return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
> +      {
> +       tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
> +       if (ret)
> +         return ret;
> +       return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
> +      }
>
>      case BUILT_IN_ISSIGNALING:
>        return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISSIGNALING);
> diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
> index 
> aba93f606eca59d31c103a05b2567fd4f3be55f3..97f85254d2c846ada99e800316855d35a557456f
>  100644
> --- a/gcc/doc/md.texi
> +++ b/gcc/doc/md.texi
> @@ -8615,6 +8615,18 @@ Return 1 if operand 1 is a finite floating point 
> number and 0
>  otherwise.  @var{m} is a scalar floating point mode.  Operand 0
>  has mode @code{SImode}, and operand 1 has mode @var{m}.
>
> +@cindex @code{isinf@var{m}2} instruction pattern
> +@item @samp{isinf@var{m}2}
> +Return 1 if operand 1 is infinite and 0 otherwise.
> +@var{m} is a scalar floating point mode.  Operand 0
> +has mode @code{SImode}, and operand 1 has mode @var{m}.
> +
> +@cindex @code{isnan@var{m}2} instruction pattern
> +@item @samp{isnan@var{m}2}
> +Return 1 if operand 1 is a @code{NaN} and 0 otherwise.
> +@var{m} is a scalar floating point mode.  Operand 0
> +has mode @code{SImode}, and operand 1 has mode @var{m}.
> +
>  @cindex @code{isnormal@var{m}2} instruction pattern
>  @item @samp{isnormal@var{m}2}
>  Return 1 if operand 1 is a normal floating point number and 0
> diff --git a/gcc/optabs.def b/gcc/optabs.def
> index 
> 87a8b85da1592646d0a3447572e842ceb158cd97..b59d02bce14cd8cd4392ac568d2547601aac4481
>  100644
> --- a/gcc/optabs.def
> +++ b/gcc/optabs.def
> @@ -363,6 +363,7 @@ OPTAB_D (isinf_optab, "isinf$a2")
>  OPTAB_D (isfinite_optab, "isfinite$a2")
>  OPTAB_D (isnormal_optab, "isnormal$a2")
>  OPTAB_D (issignaling_optab, "issignaling$a2")
> +OPTAB_D (isnan_optab, "isnan$a2")
>  OPTAB_D (ldexp_optab, "ldexp$a3")
>  OPTAB_D (log10_optab, "log10$a2")
>  OPTAB_D (log1p_optab, "log1p$a2")
>
>

Reply via email to