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


Reply via email to