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