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") > >