On Wed, Aug 27, 2025 at 7:13 PM Wilco Dijkstra <[email protected]> wrote:
>
> ping
>
> 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.
>
> Passes regress, OK for commit?
>
> gcc:
> PR middle-end/101852
> * 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}.
> +
The above is unrelated?
Otherwise OK.
Thanks,
Richard.
> +@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")
>