]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rtl.def: Add unordered fp comparisions.
authorRichard Henderson <rth@gcc.gnu.org>
Mon, 24 Jan 2000 20:10:04 +0000 (12:10 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Mon, 24 Jan 2000 20:10:04 +0000 (12:10 -0800)
        * rtl.def: Add unordered fp comparisions.
        * tree.def: Likewise.
* tree.h: Add ISO C 9x unordered fp comparision builtins.

* builtins.c (expand_tree_builtin): New function.
* c-typeck.c (build_function_call): Use it.
(build_binary_op): Support unordered compares.
* c-common.c (c_common_nodes_and_builtins): Add unordered compares.

* combine.c (known_cond): Handle reverse_condition returning UNKNOWN.
(reversible_comparison_p): Allow UNORDERED/ORDERED to be reversed.
* cse.c (fold_rtx): Check FLOAT_MODE_P before reversing.
(record_jump_equiv): Handle reverse_condition returning UNKNOWN.
* jump.c (reverse_condition): Don't abort for UNLE etc, but
return UNKNOWN.
(swap_condition): Handle unordered compares.
(thread_jumps): Check can_reverse before reversing.
* loop.c (get_condition): Likewise.  Allow UNORERED/ORDERED to be
reversed for FP.

* optabs.c (can_compare_p): New argument CODE.  Verify branch or
setcc is present before acking for cmp_optab.  Update all callers.
(prepare_float_lib_cmp, init_optabs): Handle UNORDERED.
* expmed.c (do_cmp_and_jump): Update for can_compare_p.
* expr.c (expand_expr): Likewise.  Support unordered compares.
(do_jump, do_store_flag): Likewise.
* expr.h (enum libfunc_index): Add unordered compares.

* Makefile.in (FPBIT_FUNCS): Add _unord_sf.
(DPBIT_FUNCS): Add _unord_df.
* config/fp-bit.c (_unord_f2): New.
* fp-test.c (main): Try unordered compare builtins.

* alpha-protos.h (alpha_fp_comparison_operator): Declare.
* alpha.c (alpha_comparison_operator): Check mode properly.
(alpha_swapped_comparison_operator): Likewise.
(signed_comparison_operator): Likewise.
(alpha_fp_comparison_operator): New.
(alpha_emit_conditional_branch): Handle unordered compares.
* alpha.h (PREDICATE_CODES): Update.
* alpha.md (fp compares): Use alpha_fp_comparison_operator.
(bunordered, bordered): New.

* cp/call.c (build_over_call): Use expand_tree_builtin.
* cp/typeck.c (build_function_call_real): Likewise.
(build_binary_op_nodefault): Handle unordered compares.

* gcc.c-torture/execute/ieee/fp-cmp-4.c: New.

From-SVN: r31591

27 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/builtins.c
gcc/c-common.c
gcc/c-typeck.c
gcc/combine.c
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/alpha/alpha.md
gcc/config/fp-bit.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/typeck.c
gcc/cse.c
gcc/expmed.c
gcc/expr.c
gcc/expr.h
gcc/fp-test.c
gcc/jump.c
gcc/loop.c
gcc/optabs.c
gcc/rtl.def
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-4.c [new file with mode: 0644]
gcc/tree.def
gcc/tree.h

index 87611ce4dbd7cef0744c05c70b9572e704b2568c..159d95b951ec257abb750aade327978a32fe29e1 100644 (file)
@@ -1,3 +1,48 @@
+2000-01-24  Richard Henderson  <rth@cygnus.com>
+
+       * rtl.def: Add unordered fp comparisions.
+       * tree.def: Likewise.
+       * tree.h: Add ISO C 9x unordered fp comparision builtins.
+
+       * builtins.c (expand_tree_builtin): New function.
+       * c-typeck.c (build_function_call): Use it.
+       (build_binary_op): Support unordered compares.
+       * c-common.c (c_common_nodes_and_builtins): Add unordered compares.
+
+       * combine.c (known_cond): Handle reverse_condition returning UNKNOWN.
+       (reversible_comparison_p): Allow UNORDERED/ORDERED to be reversed.
+       * cse.c (fold_rtx): Check FLOAT_MODE_P before reversing.
+       (record_jump_equiv): Handle reverse_condition returning UNKNOWN.
+       * jump.c (reverse_condition): Don't abort for UNLE etc, but
+       return UNKNOWN.
+       (swap_condition): Handle unordered compares.
+       (thread_jumps): Check can_reverse before reversing.
+       * loop.c (get_condition): Likewise.  Allow UNORERED/ORDERED to be
+       reversed for FP.
+
+       * optabs.c (can_compare_p): New argument CODE.  Verify branch or
+       setcc is present before acking for cmp_optab.  Update all callers.
+       (prepare_float_lib_cmp, init_optabs): Handle UNORDERED.
+       * expmed.c (do_cmp_and_jump): Update for can_compare_p.
+       * expr.c (expand_expr): Likewise.  Support unordered compares.
+       (do_jump, do_store_flag): Likewise.
+       * expr.h (enum libfunc_index): Add unordered compares.
+
+       * Makefile.in (FPBIT_FUNCS): Add _unord_sf.
+       (DPBIT_FUNCS): Add _unord_df.
+       * config/fp-bit.c (_unord_f2): New.
+       * fp-test.c (main): Try unordered compare builtins.
+
+       * alpha-protos.h (alpha_fp_comparison_operator): Declare.
+       * alpha.c (alpha_comparison_operator): Check mode properly.
+       (alpha_swapped_comparison_operator): Likewise.
+       (signed_comparison_operator): Likewise.
+       (alpha_fp_comparison_operator): New.
+       (alpha_emit_conditional_branch): Handle unordered compares.
+       * alpha.h (PREDICATE_CODES): Update.
+       * alpha.md (fp compares): Use alpha_fp_comparison_operator.
+       (bunordered, bordered): New.
+
 2000-01-24  Richard Henderson  <rth@cygnus.com>
 
        * alpha.c (alpha_emit_xfloating_cvt): Thinko in operand manipulation.
@@ -139,8 +184,8 @@ Mon Jan 24 16:50:08 MET 2000  Jan Hubicka  <jh@suse.cz>
 
 2000-01-22  Alan Modra <alan@SPRI.Levels.UniSA.Edu.Au>
 
-        * config/elfos.h (UNIQUE_SECTION): Restore uninitialised data
-        section naming to that prior to 2000-01-07 patch.
+       * config/elfos.h (UNIQUE_SECTION): Restore uninitialised data
+       section naming to that prior to 2000-01-07 patch.
        * config/mips/elf.h (UNIQUE_SECTION): Ditto.
        * config/mips/elf64.h (UNIQUE_SECTION): Ditto.
        * config/mips/iris6gld.h (UNIQUE_SECTION): Ditto.
@@ -188,18 +233,18 @@ Mon Jan 24 16:50:08 MET 2000  Jan Hubicka  <jh@suse.cz>
 2000-01-20  Zack Weinberg  <zack@wolery.cumb.org>
 
        * Makefile.in (fixinc.sh): Depend on specs.
-        * fixinc/Makefile.in: Add rule to create machname.h.
-        (fixlib.o): Depend on machname.h.
-        * fixinc/fixtests.c (machine_name): New test.
-        * fixinc/fixfixes.c (machine_name): New fix.
-        * fixinc/fixlib.c (mn_get_regexps): New helper function for
-        the machine_name test and fix.
-        * fixinc/fixlib.h: Prototype it.
-        * fixinc/inclhack.def (machine_name): Use the C test and fix.
+       * fixinc/Makefile.in: Add rule to create machname.h.
+       (fixlib.o): Depend on machname.h.
+       * fixinc/fixtests.c (machine_name): New test.
+       * fixinc/fixfixes.c (machine_name): New fix.
+       * fixinc/fixlib.c (mn_get_regexps): New helper function for
+       the machine_name test and fix.
+       * fixinc/fixlib.h: Prototype it.
+       * fixinc/inclhack.def (machine_name): Use the C test and fix.
        * fixinc/fixincl.x, fixinc/inclhack.sh: Rebuild.
 
-        * gcc.c (do_spec_1) [case P]: Take care not to create
-        identifiers with three leading or trailing underscores.
+       * gcc.c (do_spec_1) [case P]: Take care not to create
+       identifiers with three leading or trailing underscores.
 
        * fixinc/Makefile.in (FIXINC_DEFS): Add -DIN_GCC.
        (fixincl): Don't specify libraries twice on link line.
@@ -851,8 +896,8 @@ Sat Jan 15 15:41:14 EST 2000  John Wehle  (john@feith.com)
 2000-01-14  Clinton Popetz  <cpopetz@cygnus.com>
 
        * config/mips/mips.h (REGISTER_MOVE_COST): Remove redundant
-        case for moving from HI/LO/HI_LO_REG.  This makes the behavior
-        match the comment for MIPS16.
+       case for moving from HI/LO/HI_LO_REG.  This makes the behavior
+       match the comment for MIPS16.
 
 Fri Jan 14 00:28:06 2000  Jeffrey A Law  (law@cygnus.com)
 
@@ -878,7 +923,7 @@ Thu Jan 13 23:44:03 2000  Richard Henderson  <rth@cygnus.com>
        Use emit_jump_insn for the return insn.
 
 Thu Jan 13 14:46:03 2000  Jason Eckhardt  <jle@cygnus.com>
-                          Stan Cox  <scox@cygnus.com>
+                         Stan Cox  <scox@cygnus.com>
 
        * predict.c: New file. Preliminary infrastructure work for static
        branch prediction and basic block reordering.
@@ -1278,21 +1323,21 @@ Tue Jan 11 18:59:35 MET 2000  Jan Hubicka <jh@suse.cz>
 
 2000-01-11  Clinton Popetz  <cpopetz@cygnus.com>
 
-        * config/mips/mips.c (mips_va_arg): For EABI, emit the queued
-        integer vararg POSTINCREMENT before the destination of the jump
-        for the hard fp case. 
-        (function_arg_pass_by_reference): Pass a copy of CUM to 
+       * config/mips/mips.c (mips_va_arg): For EABI, emit the queued
+       integer vararg POSTINCREMENT before the destination of the jump
+       for the hard fp case. 
+       (function_arg_pass_by_reference): Pass a copy of CUM to 
        FUNCTION_ARG.
-        
-        * config/mips/mips.h (GO_IF_LEGITIMATE_ADDRESS): Move check
-        for CONSTANT_ADDRESS_P above while loop for subreg.
+       
+       * config/mips/mips.h (GO_IF_LEGITIMATE_ADDRESS): Move check
+       for CONSTANT_ADDRESS_P above while loop for subreg.
 
 2000-01-11  Clinton Popetz  <cpopetz@cygnus.com>
 
        * flow.c (propagate_block): When a prologue/epilogue insn
-        is marked dead, unconditionally clear libcall_is_dead and
-        insn_is_dead, and only dump rtl if warnings aren't being
-        suppressed.
+       is marked dead, unconditionally clear libcall_is_dead and
+       insn_is_dead, and only dump rtl if warnings aren't being
+       suppressed.
 
 Tue Jan 11 16:26:47 MET 2000  Jan Hubicka <jh@suse.cz>
 
@@ -1660,11 +1705,11 @@ Thu Jan  6 13:44:59 CET 2000  Jan Hubicka  <jh@suse.cz>
 
        * configure.in (m68*-*-rtemscoff*): New target, formal name for
        old m68*-*-rtems*.
-        (m68*-*-rtemself*): New target.
+       (m68*-*-rtemself*): New target.
        (mips64orion-*-rtems*): Remove duplicate definition of tm_file.
        (sparc*-*-rtemsaout*): New target, formal name for old sparc*-*-rtems*.
-        (sparc*-*-rtemself*): New target.
-        (sparc*-*-rtems*): Now elf not a.out.
+       (sparc*-*-rtemself*): New target.
+       (sparc*-*-rtems*): Now elf not a.out.
        * config/i386/rtems.h: Include config/rtems.h.
        * config/i386/rtemself.h: Include config/rtems.h.
        * config/i960/rtems.h: Include config/rtems.h.
@@ -1956,7 +2001,7 @@ Fri Dec 31 19:10:31 1999  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
 1999-12-30  Herman A.J. ten Brugge  <Haj.Ten.Brugge@net.HCC.nl>
 
-        * genrecog.c (change_state) Corrected typo.
+       * genrecog.c (change_state) Corrected typo.
 
 1999-12-30  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
index 8d91ab318b8f7e4205b17105b93b63fb9f9f09f7..5e6b6e581813c325becf09d8fd262885f2a6d330 100644 (file)
@@ -730,12 +730,12 @@ LIB2FUNCS_EH = _eh
 
 FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
     _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
-    _lt_sf _le_sf _si_to_sf _sf_to_si _negate_sf _make_sf \
+    _lt_sf _le_sf _unord_sf _si_to_sf _sf_to_si _negate_sf _make_sf \
     _sf_to_df _thenan_sf _sf_to_usi _df_to_usi
 
 DPBIT_FUNCS = _pack_df _unpack_df _addsub_df _mul_df _div_df \
     _fpcmp_parts_df _compare_df _eq_df _ne_df _gt_df _ge_df \
-    _lt_df _le_df _si_to_df _df_to_si _negate_df _make_df \
+    _lt_df _le_df _unord_df _si_to_df _df_to_si _negate_df _make_df \
     _df_to_sf _thenan_df _sf_to_usi _df_to_usi
 
 # The files that "belong" in CONFIG_H are deliberately omitted
index 1ca5b5dbb5e7f6dfab2daf2c5081164ecd21a23e..fcb6a7aa676fa29ae4330e77e4f837844ab2d603 100644 (file)
@@ -2520,3 +2520,100 @@ expand_builtin (exp, target, subtarget, mode, ignore)
      to be called normally.  */
   return expand_call (exp, target, ignore);
 }
+
+/* Recognize certain built-in functions so we can make tree-codes
+   other than CALL_EXPR.  We do this when it enables fold-const.c
+   to do something useful.  */
+
+tree
+expand_tree_builtin (function, params, coerced_params)
+     tree function, params, coerced_params;
+{
+  enum tree_code code;
+
+  if (DECL_BUILT_IN_CLASS (function) != BUILT_IN_NORMAL)
+    return NULL_TREE;
+
+  switch (DECL_FUNCTION_CODE (function))
+    {
+    case BUILT_IN_ABS:
+    case BUILT_IN_LABS:
+    case BUILT_IN_FABS:
+      if (coerced_params == 0)
+       return integer_zero_node;
+      return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
+
+    case BUILT_IN_ISGREATER:
+      if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+       code = UNLE_EXPR;
+      else
+       code = LE_EXPR;
+      goto unordered_cmp;
+
+    case BUILT_IN_ISGREATEREQUAL:
+      if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+       code = UNLT_EXPR;
+      else
+       code = LT_EXPR;
+      goto unordered_cmp;
+
+    case BUILT_IN_ISLESS:
+      if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+       code = UNGE_EXPR;
+      else
+       code = GE_EXPR;
+      goto unordered_cmp;
+
+    case BUILT_IN_ISLESSEQUAL:
+      if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+       code = UNGT_EXPR;
+      else
+       code = GT_EXPR;
+      goto unordered_cmp;
+
+    case BUILT_IN_ISLESSGREATER:
+      if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+       code = UNEQ_EXPR;
+      else
+       code = EQ_EXPR;
+      goto unordered_cmp;
+
+    case BUILT_IN_ISUNORDERED:
+      if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
+       return integer_zero_node;
+      code = UNORDERED_EXPR;
+      goto unordered_cmp;
+
+    unordered_cmp:
+      {
+       tree arg0, arg1;
+
+       if (params == 0
+           || TREE_CHAIN (params) == 0)
+         {
+           error ("too few arguments to function `%s'",
+                  IDENTIFIER_POINTER (DECL_NAME (function)));
+           return error_mark_node;
+         }
+       else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
+         {
+           error ("too many arguments to function `%s'",
+                  IDENTIFIER_POINTER (DECL_NAME (function)));
+           return error_mark_node;
+         }
+
+       arg0 = TREE_VALUE (params);
+       arg1 = TREE_VALUE (TREE_CHAIN (params));
+       arg0 = build_binary_op (code, arg0, arg1, 0);
+       if (code != UNORDERED_EXPR)
+         arg0 = build_unary_op (TRUTH_NOT_EXPR, arg0, 0);
+       return arg0;
+      }
+      break;
+
+    default:
+      break;
+    }
+
+  return NULL_TREE;
+}
index 0ce1ff19a4fc8163534f846c46309e8f891af413..6d9181094b49f210dd420c1de8c4c664b32c5e03 100644 (file)
@@ -3710,6 +3710,20 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins)
   builtin_function ("__builtin_trap", void_ftype, BUILT_IN_TRAP,
                    BUILT_IN_NORMAL, NULL_PTR);
 
+  /* ISO C99 IEEE Unordered compares.  */
+  builtin_function ("__builtin_isgreater", default_function_type,
+                   BUILT_IN_ISGREATER, BUILT_IN_NORMAL, NULL_PTR);
+  builtin_function ("__builtin_isgreaterequal", default_function_type,
+                   BUILT_IN_ISGREATEREQUAL, BUILT_IN_NORMAL, NULL_PTR);
+  builtin_function ("__builtin_isless", default_function_type,
+                   BUILT_IN_ISLESS, BUILT_IN_NORMAL, NULL_PTR);
+  builtin_function ("__builtin_islessequal", default_function_type,
+                   BUILT_IN_ISLESSEQUAL, BUILT_IN_NORMAL, NULL_PTR);
+  builtin_function ("__builtin_islessgreater", default_function_type,
+                   BUILT_IN_ISLESSGREATER, BUILT_IN_NORMAL, NULL_PTR);
+  builtin_function ("__builtin_isunordered", default_function_type,
+                   BUILT_IN_ISUNORDERED, BUILT_IN_NORMAL, NULL_PTR);
+
   /* Untyped call and return.  */
   builtin_function ("__builtin_apply_args", ptr_ftype,
                    BUILT_IN_APPLY_ARGS, BUILT_IN_NORMAL, NULL_PTR);
index a810a3bdf0eafcc896575a9ce46b8f77d98ef5d8..f85931ad4a020636a061907cc5e2b3e673ef63d1 100644 (file)
@@ -1405,7 +1405,7 @@ build_function_call (function, params)
 {
   register tree fntype, fundecl = 0;
   register tree coerced_params;
-  tree name = NULL_TREE, assembler_name = NULL_TREE;
+  tree name = NULL_TREE, assembler_name = NULL_TREE, result;
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
@@ -1460,30 +1460,21 @@ build_function_call (function, params)
 
   if (TREE_CODE (function) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
-      && DECL_BUILT_IN (TREE_OPERAND (function, 0))
-      && DECL_BUILT_IN_CLASS (TREE_OPERAND (function, 0)) == BUILT_IN_NORMAL)
-    switch (DECL_FUNCTION_CODE (TREE_OPERAND (function, 0)))
-      {
-      case BUILT_IN_ABS:
-      case BUILT_IN_LABS:
-      case BUILT_IN_FABS:
-       if (coerced_params == 0)
-         return integer_zero_node;
-       return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
-      default:
-       break;
-      }
+      && DECL_BUILT_IN (TREE_OPERAND (function, 0)))
+    {
+      result = expand_tree_builtin (TREE_OPERAND (function, 0),
+                                   params, coerced_params);
+      if (result)
+       return result;
+    }
 
-  {
-    register tree result
-      = build (CALL_EXPR, TREE_TYPE (fntype),
-              function, coerced_params, NULL_TREE);
-
-    TREE_SIDE_EFFECTS (result) = 1;
-    if (TREE_TYPE (result) == void_type_node)
-      return result;
-    return require_complete_type (result);
-  }
+  result = build (CALL_EXPR, TREE_TYPE (fntype),
+                 function, coerced_params, NULL_TREE);
+
+  TREE_SIDE_EFFECTS (result) = 1;
+  if (TREE_TYPE (result) == void_type_node)
+    return result;
+  return require_complete_type (result);
 }
 \f
 /* Convert the argument expressions in the list VALUES
@@ -2233,7 +2224,24 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
            pedwarn ("comparison between pointer and integer");
        }
       break;
-      
+
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+    case UNNE_EXPR:
+      build_type = integer_type_node;
+      if (code0 != REAL_TYPE || code1 != REAL_TYPE)
+       {
+         error ("unordered comparison on non-floating point argument");
+         return error_mark_node;
+       }
+      common = 1;
+      break;
+
     default:
       break;
     }
index 99fe499756bdd3824d1d5ffe460fcce199233227..8d578eb6691574fcf5a3bb86b09f81ad2ee6f743 100644 (file)
@@ -7313,11 +7313,17 @@ known_cond (x, cond, reg, val)
       if (rtx_equal_p (XEXP (x, 0), reg) && rtx_equal_p (XEXP (x, 1), val))
        {
          if (GET_RTX_CLASS (code) == '<')
-           return (comparison_dominates_p (cond, code) ? const_true_rtx
-                   : (comparison_dominates_p (cond,
-                                              reverse_condition (code))
-                      ? const0_rtx : x));
+           {
+             if (comparison_dominates_p (cond, code))
+               return const_true_rtx;
 
+             code = reverse_condition (code);
+             if (code != UNKNOWN
+                 && comparison_dominates_p (cond, code))
+               return const0_rtx;
+             else
+               return x;
+           }
          else if (code == SMAX || code == SMIN
                   || code == UMIN || code == UMAX)
            {
@@ -10852,7 +10858,8 @@ reversible_comparison_p (x)
 {
   if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
       || flag_fast_math
-      || GET_CODE (x) == NE || GET_CODE (x) == EQ)
+      || GET_CODE (x) == NE || GET_CODE (x) == EQ
+      || GET_CODE (x) == UNORDERED || GET_CODE (x) == ORDERED)
     return 1;
 
   switch (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))))
index c29063e9fd221766bb45ca91ff3bd4c2f0b5c057..693fa245bcc76dff82950eb5f55547c528b770c7 100644 (file)
@@ -58,6 +58,7 @@ extern int call_operand PARAMS ((rtx, enum machine_mode));
 extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode));
 extern int alpha_swapped_comparison_operator PARAMS ((rtx, enum machine_mode));
 extern int signed_comparison_operator PARAMS ((rtx, enum machine_mode));
+extern int alpha_fp_comparison_operator PARAMS ((rtx, enum machine_mode));
 extern int divmod_operator PARAMS ((rtx, enum machine_mode));
 extern int aligned_memory_operand PARAMS ((rtx, enum machine_mode));
 extern int unaligned_memory_operand PARAMS ((rtx, enum machine_mode));
index ca9e0ecaf3505a22959ff2b1a4baf11eae39e09a..cbc16883d6fdef334b9ef718b9737387f9863047 100644 (file)
@@ -706,7 +706,7 @@ alpha_comparison_operator (op, mode)
 {
   enum rtx_code code = GET_CODE (op);
 
-  if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<')
+  if (mode != GET_MODE (op) && mode != VOIDmode)
     return 0;
 
   return (code == EQ || code == LE || code == LT
@@ -722,7 +722,8 @@ alpha_swapped_comparison_operator (op, mode)
 {
   enum rtx_code code = GET_CODE (op);
 
-  if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<')
+  if ((mode != GET_MODE (op) && mode != VOIDmode)
+      || GET_RTX_CLASS (code) != '<')
     return 0;
 
   code = swap_condition (code);
@@ -737,16 +738,30 @@ signed_comparison_operator (op, mode)
      register rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  switch (GET_CODE (op))
-    {
-    case EQ:  case NE:  case LE:  case LT:  case GE:   case GT:
-      return 1;
+  enum rtx_code code = GET_CODE (op);
 
-    default:
-      break;
-    }
+  if (mode != GET_MODE (op) && mode != VOIDmode)
+    return 0;
 
-  return 0;
+  return (code == EQ || code == NE
+         || code == LE || code == LT
+         || code == GE || code == GT);
+}
+
+/* Return 1 if OP is a valid Alpha floating point comparison operator.
+   Here we know which comparisons are valid in which insn.  */
+
+int
+alpha_fp_comparison_operator (op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  enum rtx_code code = GET_CODE (op);
+
+  if (mode != GET_MODE (op) && mode != VOIDmode)
+    return 0;
+
+  return (code == EQ || code == LE || code == LT || code == UNORDERED);
 }
 
 /* Return 1 if this is a divide or modulus operator.  */
@@ -1484,13 +1499,15 @@ alpha_emit_conditional_branch (code)
   switch (code)
     {
     case EQ:  case LE:  case LT:  case LEU:  case LTU:
+    case UNORDERED:
       /* We have these compares: */
       cmp_code = code, branch_code = NE;
       break;
 
     case NE:
-      /* This must be reversed. */
-      cmp_code = EQ, branch_code = EQ;
+    case ORDERED:
+      /* These must be reversed. */
+      cmp_code = reverse_condition (code), branch_code = EQ;
       break;
 
     case GE:  case GT: case GEU:  case GTU:
@@ -3383,6 +3400,8 @@ print_operand (file, x, code)
          fprintf (file, "ule");
         else if (c == LTU)
          fprintf (file, "ult");
+       else if (c == UNORDERED)
+         fprintf (file, "un");
         else
          fprintf (file, "%s", GET_RTX_NAME (c));
       }
index b146a5a4c24a5dc253761e5c9997a9c296cd52ea..ad45596f0bb1d8cc5da5cb211d7c9bffde60af47 100644 (file)
@@ -2311,6 +2311,7 @@ do {                                                                      \
   {"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}},               \
   {"alpha_swapped_comparison_operator", {EQ, GE, GT, GEU, GTU}},       \
   {"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}},            \
+  {"alpha_fp_comparison_operator", {EQ, LE, LT, UNORDERED}},           \
   {"divmod_operator", {DIV, MOD, UDIV, UMOD}},                         \
   {"fp0_operand", {CONST_DOUBLE}},                                     \
   {"current_file_function_operand", {SYMBOL_REF}},                     \
index 5f0e2219bbd8d72354e26e6fe53fe2515d8f2ba7..2325483d02dc7835bb27952ca069a43ee8844042 100644 (file)
   "")
 \f
 ;; The following are the corresponding floating-point insns.  Recall
-;; we need to have variants that expand the arguments from SF mode
+;; we need to have variants that expand the arguments from SFmode
 ;; to DFmode.
 
-(define_insn ""
+(define_insn "*cmpdf_tp"
   [(set (match_operand:DF 0 "register_operand" "=&f")
-       (match_operator:DF 1 "alpha_comparison_operator"
+       (match_operator:DF 1 "alpha_fp_comparison_operator"
                           [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
                            (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
   "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
   [(set_attr "type" "fadd")
    (set_attr "trap" "yes")])
 
-(define_insn ""
+(define_insn "*cmpdf_no_tp"
   [(set (match_operand:DF 0 "register_operand" "=f")
-       (match_operator:DF 1 "alpha_comparison_operator"
+       (match_operator:DF 1 "alpha_fp_comparison_operator"
                           [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
                            (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
   "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=&f")
-       (match_operator:DF 1 "alpha_comparison_operator"
+       (match_operator:DF 1 "alpha_fp_comparison_operator"
                           [(float_extend:DF
                             (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
                            (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
-       (match_operator:DF 1 "alpha_comparison_operator"
+       (match_operator:DF 1 "alpha_fp_comparison_operator"
                           [(float_extend:DF
                             (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
                            (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=&f")
-       (match_operator:DF 1 "alpha_comparison_operator"
+       (match_operator:DF 1 "alpha_fp_comparison_operator"
                           [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
                            (float_extend:DF
                             (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
-       (match_operator:DF 1 "alpha_comparison_operator"
+       (match_operator:DF 1 "alpha_fp_comparison_operator"
                           [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
                            (float_extend:DF
                             (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=&f")
-       (match_operator:DF 1 "alpha_comparison_operator"
+       (match_operator:DF 1 "alpha_fp_comparison_operator"
                           [(float_extend:DF
                             (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
                            (float_extend:DF
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
-       (match_operator:DF 1 "alpha_comparison_operator"
+       (match_operator:DF 1 "alpha_fp_comparison_operator"
                           [(float_extend:DF
                             (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
                            (float_extend:DF
   ""
   "{ operands[1] = alpha_emit_conditional_branch (GEU); }")
 
+(define_expand "bunordered"
+  [(set (pc)
+       (if_then_else (match_dup 1)
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "{ operands[1] = alpha_emit_conditional_branch (UNORDERED); }")
+
+(define_expand "bordered"
+  [(set (pc)
+       (if_then_else (match_dup 1)
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "{ operands[1] = alpha_emit_conditional_branch (ORDERED); }")
+
 (define_expand "seq"
   [(set (match_operand:DI 0 "register_operand" "")
        (match_dup 1))]
index d7bc3de38f4ad3b88e60515ee9aaeda0baa7b990..fc496c0f0592da104e67a4cf4b7fa5fd4cb51d43 100644 (file)
@@ -1,7 +1,7 @@
 /* This is a software floating point library which can be used instead of
    the floating point routines in libgcc1.c for targets without hardware
    floating point. 
Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
  Copyright (C) 1994-1998, 2000 Free Software Foundation, Inc.
 
 This file is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -78,6 +78,8 @@ Boston, MA 02111-1307, USA.  */
 #define L_lt_df
 #define L_le_sf
 #define L_le_df
+#define L_unord_sf
+#define L_unord_df
 #define L_si_to_sf
 #define L_si_to_df
 #define L_sf_to_si
@@ -268,6 +270,7 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
 #              define _ge_f2           __gesf2
 #              define _lt_f2           __ltsf2
 #              define _le_f2           __lesf2
+#              define _unord_f2        __unordsf2
 #              define si_to_float      __floatsisf
 #              define float_to_si      __fixsfsi
 #              define float_to_usi     __fixunssfsi
@@ -285,6 +288,7 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
 #              define _ge_f2           __gedf2
 #              define _lt_f2           __ltdf2
 #              define _le_f2           __ledf2
+#              define _unord_f2        __unorddf2
 #              define si_to_float      __floatsidf
 #              define float_to_si      __fixdfsi
 #              define float_to_usi     __fixunsdfsi
@@ -1370,6 +1374,24 @@ _le_f2 (FLO_type arg_a, FLO_type arg_b)
 }
 #endif
 
+#if defined(L_unord_sf) || defined(L_unord_df)
+CMPtype
+_unord_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  return (isnan (&a) || isnan (&b);
+}
+#endif
+
 #endif /* ! US_SOFTWARE_GOFAST */
 
 #if defined(L_si_to_sf) || defined(L_si_to_df)
index 0b2cda1c9211e1f3ff2a5a0f8ae9419880df4f5e..92dcb793124294a5a9bfd5afce0cdb0b6e79b46c 100644 (file)
@@ -1,3 +1,9 @@
+2000-01-24  Richard Henderson  <rth@cygnus.com>
+
+       * call.c (build_over_call): Use expand_tree_builtin.
+       * typeck.c (build_function_call_real): Likewise.
+       (build_binary_op_nodefault): Handle unordered compares.
+
 2000-01-24  Nathan Sidwell  <sidwell@codesourcery.com>
 
        * cp-tree.h (CPTI_BAD_CAST, CPTI_BAD_TYPEID, CPTI_DCAST): New
 
 2000-01-19  Gabriel Dos Reis  <gdr@codesourcery.coom>
 
-        * typeck.c (build_unary_op): Use cp_pedwarn, not pedwarn.
+       * typeck.c (build_unary_op): Use cp_pedwarn, not pedwarn.
 
-        * typeck2.c (incomplete_type_error): Restore previous
-        cp_error and cp_error_at call sequence.
+       * typeck2.c (incomplete_type_error): Restore previous
+       cp_error and cp_error_at call sequence.
        
 2000-01-20  Brad Lucier  <lucier@math.purdue.edu>
 
index f526abfa4fec5daa7e876d810345aaadc3daf1f1..991a79dcd99f84ee7dbe3ca63f18d8383c18008c 100644 (file)
@@ -4145,19 +4145,13 @@ build_over_call (cand, args, flags)
 
   if (TREE_CODE (fn) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
-      && DECL_BUILT_IN (TREE_OPERAND (fn, 0))
-      && DECL_BUILT_IN_CLASS (TREE_OPERAND (fn, 0)) == BUILT_IN_NORMAL)
-    switch (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0)))
-      {
-      case BUILT_IN_ABS:
-      case BUILT_IN_LABS:
-      case BUILT_IN_FABS:
-       if (converted_args == 0)
-         return integer_zero_node;
-       return build_unary_op (ABS_EXPR, TREE_VALUE (converted_args), 0);
-      default:
-        break;
-      }
+      && DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
+    {
+      tree exp;
+      exp = expand_tree_builtin (TREE_OPERAND (fn, 0), args, converted_args);
+      if (exp)
+       return exp;
+    }
 
   fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args);
   if (TREE_CODE (TREE_TYPE (fn)) == VOID_TYPE)
index 2a4a668b906056463940b137e398cf0fe40ce755..29f60860ad20fcdcf14076ee304f3f6d6ed46ee5 100644 (file)
@@ -2926,6 +2926,7 @@ build_function_call_real (function, params, require_complete, flags)
   register tree fntype, fndecl;
   register tree value_type;
   register tree coerced_params;
+  tree result;
   tree name = NULL_TREE, assembler_name = NULL_TREE;
   int is_method;
 
@@ -3023,37 +3024,27 @@ build_function_call_real (function, params, require_complete, flags)
 
   if (TREE_CODE (function) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
-      && DECL_BUILT_IN (TREE_OPERAND (function, 0))
-      && DECL_BUILT_IN_CLASS (TREE_OPERAND (function, 0)) == BUILT_IN_NORMAL)
-    switch (DECL_FUNCTION_CODE (TREE_OPERAND (function, 0)))
-      {
-      case BUILT_IN_ABS:
-      case BUILT_IN_LABS:
-      case BUILT_IN_FABS:
-       if (coerced_params == 0)
-         return integer_zero_node;
-       return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
-
-      default:
-       break;
-      }
+      && DECL_BUILT_IN (TREE_OPERAND (function, 0)))
+    {
+      result = expand_tree_builtin (TREE_OPERAND (function, 0),
+                                   params, coerced_params);
+      if (result)
+       return result;
+    }
 
   /* C++ */
   value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
-  {
-    register tree result
-      = build_call (function, value_type, coerced_params);
+  result = build_call (function, value_type, coerced_params);
 
-    if (require_complete)
-      {
-       if (TREE_CODE (value_type) == VOID_TYPE)
-         return result;
-       result = require_complete_type (result);
-      }
-    if (IS_AGGR_TYPE (value_type))
-      result = build_cplus_new (value_type, result);
-    return convert_from_reference (result);
-  }
+  if (require_complete)
+    {
+      if (TREE_CODE (value_type) == VOID_TYPE)
+       return result;
+      result = require_complete_type (result);
+    }
+  if (IS_AGGR_TYPE (value_type))
+    result = build_cplus_new (value_type, result);
+  return convert_from_reference (result);
 }
 
 tree
@@ -3792,6 +3783,23 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
        }
       break;
 
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+    case UNNE_EXPR:
+      build_type = integer_type_node;
+      if (code0 != REAL_TYPE || code1 != REAL_TYPE)
+       {
+         error ("unordered comparison on non-floating point argument");
+         return error_mark_node;
+       }
+      common = 1;
+      break;
+
     default:
       break;
     }
index b346199097a6dd3df5c6a5a8d8f0e08cb00ac277..9aced05f6072b21618e12971a3ae25bfbb3436fd 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -3718,9 +3718,9 @@ fold_rtx (x, insn)
                      struct qty_table_elem *ent = &qty_table[qty];
 
                      if ((comparison_dominates_p (ent->comparison_code, code)
-                          || (comparison_dominates_p (ent->comparison_code,
-                                                      reverse_condition (code))
-                              && ! FLOAT_MODE_P (mode_arg0)))
+                          || (! FLOAT_MODE_P (mode_arg0)
+                              && comparison_dominates_p (ent->comparison_code,
+                                                         reverse_condition (code))))
                          && (rtx_equal_p (ent->comparison_const, folded_arg1)
                              || (const_arg1
                                  && rtx_equal_p (ent->comparison_const,
@@ -4156,6 +4156,10 @@ record_jump_equiv (insn, taken)
     {
       reversed_nonequality = (code != EQ && code != NE);
       code = reverse_condition (code);
+
+      /* Don't remember if we can't find the inverse.  */
+      if (code == UNKNOWN)
+       return;
     }
 
   /* The mode is the mode of the non-constant.  */
index 63441875e9bda5b476c1834bbbeae2f652c1a203..92d9a16537580cd8d8ed1ad399b4cc731f128f7f 100644 (file)
@@ -4561,7 +4561,8 @@ do_cmp_and_jump (arg1, arg2, op, mode, label)
   /* If this mode is an integer too wide to compare properly,
      compare word by word.  Rely on cse to optimize constant cases.  */
 
-  if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode, ccp_jump))
+  if (GET_MODE_CLASS (mode) == MODE_INT
+      && ! can_compare_p (op, mode, ccp_jump))
     {
       rtx label2 = gen_label_rtx ();
 
index 9e07dafda6abfa18109128544472c083fba3a86c..62f7d56b057dcf8f9b93a12f456475d49442cd13 100644 (file)
@@ -7537,7 +7537,8 @@ expand_expr (exp, target, tmode, modifier)
 
       /* If this mode is an integer too wide to compare properly,
         compare word by word.  Rely on cse to optimize constant cases.  */
-      if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode, ccp_jump))
+      if (GET_MODE_CLASS (mode) == MODE_INT
+         && ! can_compare_p (GE, mode, ccp_jump))
        {
          if (code == MAX_EXPR)
            do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type),
@@ -7618,6 +7619,14 @@ expand_expr (exp, target, tmode, modifier)
     case GE_EXPR:
     case EQ_EXPR:
     case NE_EXPR:
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+    case UNNE_EXPR:
       preexpand_calls (exp);
       temp = do_store_flag (exp, target, tmode != VOIDmode ? tmode : mode, 0);
       if (temp != 0)
@@ -9413,7 +9422,7 @@ do_jump (exp, if_false_label, if_true_label)
          do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
 
        else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
-                && !can_compare_p (TYPE_MODE (inner_type), ccp_jump))
+                && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
          do_jump_by_parts_equality (exp, if_false_label, if_true_label);
        else
          do_compare_and_jump (exp, EQ, EQ, if_false_label, if_true_label);
@@ -9453,7 +9462,7 @@ do_jump (exp, if_false_label, if_true_label)
          do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
 
        else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
-                && !can_compare_p (TYPE_MODE (inner_type), ccp_jump))
+                && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
          do_jump_by_parts_equality (exp, if_true_label, if_false_label);
        else
          do_compare_and_jump (exp, NE, NE, if_false_label, if_true_label);
@@ -9463,7 +9472,7 @@ do_jump (exp, if_false_label, if_true_label)
     case LT_EXPR:
       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
       if (GET_MODE_CLASS (mode) == MODE_INT
-         && ! can_compare_p (mode, ccp_jump))
+         && ! can_compare_p (LT, mode, ccp_jump))
        do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label);
       else
        do_compare_and_jump (exp, LT, LTU, if_false_label, if_true_label);
@@ -9472,7 +9481,7 @@ do_jump (exp, if_false_label, if_true_label)
     case LE_EXPR:
       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
       if (GET_MODE_CLASS (mode) == MODE_INT
-         && ! can_compare_p (mode, ccp_jump))
+         && ! can_compare_p (LE, mode, ccp_jump))
        do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label);
       else
        do_compare_and_jump (exp, LE, LEU, if_false_label, if_true_label);
@@ -9481,7 +9490,7 @@ do_jump (exp, if_false_label, if_true_label)
     case GT_EXPR:
       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
       if (GET_MODE_CLASS (mode) == MODE_INT
-         && ! can_compare_p (mode, ccp_jump))
+         && ! can_compare_p (GT, mode, ccp_jump))
        do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label);
       else
        do_compare_and_jump (exp, GT, GTU, if_false_label, if_true_label);
@@ -9490,12 +9499,87 @@ do_jump (exp, if_false_label, if_true_label)
     case GE_EXPR:
       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
       if (GET_MODE_CLASS (mode) == MODE_INT
-         && ! can_compare_p (mode, ccp_jump))
+         && ! can_compare_p (GE, mode, ccp_jump))
        do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label);
       else
        do_compare_and_jump (exp, GE, GEU, if_false_label, if_true_label);
       break;
 
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+      {
+       enum rtx_code cmp, rcmp;
+       int do_rev;
+
+       if (code == UNORDERED_EXPR)
+         cmp = UNORDERED, rcmp = ORDERED;
+       else
+         cmp = ORDERED, rcmp = UNORDERED;
+        mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+       do_rev = 0;
+       if (! can_compare_p (cmp, mode, ccp_jump)
+           && (can_compare_p (rcmp, mode, ccp_jump)
+               /* If the target doesn't provide either UNORDERED or ORDERED
+                  comparisons, canonicalize on UNORDERED for the library.  */
+               || rcmp == UNORDERED))
+         do_rev = 1;
+
+        if (! do_rev)
+         do_compare_and_jump (exp, cmp, cmp, if_false_label, if_true_label);
+       else
+         do_compare_and_jump (exp, rcmp, rcmp, if_true_label, if_false_label);
+      }
+      break;
+
+    {
+      enum rtx_code rcode1;
+      enum tree_code tcode2;
+
+      case UNLT_EXPR:
+       rcode1 = UNLT;
+       tcode2 = LT_EXPR;
+       goto unordered_bcc;
+      case UNLE_EXPR:
+       rcode1 = UNLE;
+       tcode2 = LE_EXPR;
+       goto unordered_bcc;
+      case UNGT_EXPR:
+       rcode1 = UNGT;
+       tcode2 = GT_EXPR;
+       goto unordered_bcc;
+      case UNGE_EXPR:
+       rcode1 = UNGE;
+       tcode2 = GE_EXPR;
+       goto unordered_bcc;
+      case UNEQ_EXPR:
+       rcode1 = UNEQ;
+       tcode2 = EQ_EXPR;
+       goto unordered_bcc;
+      case UNNE_EXPR:
+       rcode1 = UNNE;
+       tcode2 = NE_EXPR;
+      unordered_bcc:
+        mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+       if (can_compare_p (rcode1, mode, ccp_jump))
+         do_compare_and_jump (exp, rcode1, rcode1, if_false_label,
+                              if_true_label);
+       else
+         {
+           tree op0 = save_expr (TREE_OPERAND (exp, 0));
+           tree op1 = save_expr (TREE_OPERAND (exp, 1));
+           tree cmp0, cmp1;
+
+           /* If the target doesn't support combined unordered 
+              compares, decompose into UNORDERED + comparison.  */
+           cmp0 = fold (build (UNORDERED_EXPR, TREE_TYPE (exp), op0, op1));
+           cmp1 = fold (build (tcode2, TREE_TYPE (exp), op0, op1));
+           exp = build (TRUTH_ORIF_EXPR, TREE_TYPE (exp), cmp0, cmp1);
+           do_jump (exp, if_false_label, if_true_label);
+         }
+      }
+      break;
+
     default:
     normal:
       temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
@@ -9519,7 +9603,7 @@ do_jump (exp, if_false_label, if_true_label)
            emit_jump (target);
        }
       else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
-              && ! can_compare_p (GET_MODE (temp), ccp_jump))
+              && ! can_compare_p (NE, GET_MODE (temp), ccp_jump))
        /* Note swapping the labels gives us not-equal.  */
        do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label);
       else if (GET_MODE (temp) != VOIDmode)
@@ -10059,6 +10143,32 @@ do_store_flag (exp, target, mode, only_cheap)
       else
        code = unsignedp ? GEU : GE;
       break;
+
+    case UNORDERED_EXPR:
+      code = UNORDERED;
+      break;
+    case ORDERED_EXPR:
+      code = ORDERED;
+      break;
+    case UNLT_EXPR:
+      code = UNLT;
+      break;
+    case UNLE_EXPR:
+      code = UNLE;
+      break;
+    case UNGT_EXPR:
+      code = UNGT;
+      break;
+    case UNGE_EXPR:
+      code = UNGE;
+      break;
+    case UNEQ_EXPR:
+      code = UNEQ;
+      break;
+    case UNNE_EXPR:
+      code = UNNE;
+      break;
+
     default:
       abort ();
     }
@@ -10134,8 +10244,9 @@ do_store_flag (exp, target, mode, only_cheap)
     }
 
   /* Now see if we are likely to be able to do this.  Return if not.  */
-  if (! can_compare_p (operand_mode, ccp_store_flag))
+  if (! can_compare_p (code, operand_mode, ccp_store_flag))
     return 0;
+
   icode = setcc_gen_code[(int) code];
   if (icode == CODE_FOR_nothing
       || (only_cheap && insn_data[(int) icode].operand[0].mode != mode))
index 9442f0fabd85ea820f709e877e3394dfd5ae029b..95c694210ce788057d4e7edfa04c5d236f736191 100644 (file)
@@ -499,6 +499,7 @@ enum libfunc_index
   LTI_gehf2,
   LTI_lthf2,
   LTI_lehf2,
+  LTI_unordhf2,
 
   LTI_eqsf2,
   LTI_nesf2,
@@ -506,6 +507,7 @@ enum libfunc_index
   LTI_gesf2,
   LTI_ltsf2,
   LTI_lesf2,
+  LTI_unordsf2,
 
   LTI_eqdf2,
   LTI_nedf2,
@@ -513,6 +515,7 @@ enum libfunc_index
   LTI_gedf2,
   LTI_ltdf2,
   LTI_ledf2,
+  LTI_unorddf2,
 
   LTI_eqxf2,
   LTI_nexf2,
@@ -520,6 +523,7 @@ enum libfunc_index
   LTI_gexf2,
   LTI_ltxf2,
   LTI_lexf2,
+  LTI_unordxf2,
 
   LTI_eqtf2,
   LTI_netf2,
@@ -527,6 +531,7 @@ enum libfunc_index
   LTI_getf2,
   LTI_lttf2,
   LTI_letf2,
+  LTI_unordtf2,
 
   LTI_floatsisf,
   LTI_floatdisf,
@@ -627,6 +632,7 @@ extern rtx libfunc_table[LTI_MAX];
 #define gehf2_libfunc  (libfunc_table[LTI_gehf2])
 #define lthf2_libfunc  (libfunc_table[LTI_lthf2])
 #define lehf2_libfunc  (libfunc_table[LTI_lehf2])
+#define unordhf2_libfunc       (libfunc_table[LTI_unordhf2])
 
 #define eqsf2_libfunc  (libfunc_table[LTI_eqsf2])
 #define nesf2_libfunc  (libfunc_table[LTI_nesf2])
@@ -634,6 +640,7 @@ extern rtx libfunc_table[LTI_MAX];
 #define gesf2_libfunc  (libfunc_table[LTI_gesf2])
 #define ltsf2_libfunc  (libfunc_table[LTI_ltsf2])
 #define lesf2_libfunc  (libfunc_table[LTI_lesf2])
+#define unordsf2_libfunc       (libfunc_table[LTI_unordsf2])
 
 #define eqdf2_libfunc  (libfunc_table[LTI_eqdf2])
 #define nedf2_libfunc  (libfunc_table[LTI_nedf2])
@@ -641,6 +648,7 @@ extern rtx libfunc_table[LTI_MAX];
 #define gedf2_libfunc  (libfunc_table[LTI_gedf2])
 #define ltdf2_libfunc  (libfunc_table[LTI_ltdf2])
 #define ledf2_libfunc  (libfunc_table[LTI_ledf2])
+#define unorddf2_libfunc       (libfunc_table[LTI_unorddf2])
 
 #define eqxf2_libfunc  (libfunc_table[LTI_eqxf2])
 #define nexf2_libfunc  (libfunc_table[LTI_nexf2])
@@ -648,6 +656,7 @@ extern rtx libfunc_table[LTI_MAX];
 #define gexf2_libfunc  (libfunc_table[LTI_gexf2])
 #define ltxf2_libfunc  (libfunc_table[LTI_ltxf2])
 #define lexf2_libfunc  (libfunc_table[LTI_lexf2])
+#define unordxf2_libfunc       (libfunc_table[LTI_unordxf2])
 
 #define eqtf2_libfunc  (libfunc_table[LTI_eqtf2])
 #define netf2_libfunc  (libfunc_table[LTI_netf2])
@@ -655,6 +664,7 @@ extern rtx libfunc_table[LTI_MAX];
 #define getf2_libfunc  (libfunc_table[LTI_getf2])
 #define lttf2_libfunc  (libfunc_table[LTI_lttf2])
 #define letf2_libfunc  (libfunc_table[LTI_letf2])
+#define unordtf2_libfunc       (libfunc_table[LTI_unordtf2])
 
 #define floatsisf_libfunc      (libfunc_table[LTI_floatsisf])
 #define floatdisf_libfunc      (libfunc_table[LTI_floatdisf])
@@ -795,9 +805,11 @@ enum can_compare_purpose
   ccp_cmov,
   ccp_store_flag
 };
+
 /* Nonzero if a compare of mode MODE can be done straightforwardly
    (without splitting it into pieces).  */
-extern int can_compare_p PARAMS ((enum machine_mode, enum can_compare_purpose));
+extern int can_compare_p PARAMS ((enum rtx_code, enum machine_mode,
+                                 enum can_compare_purpose));
 
 extern void prepare_cmp_insn PARAMS ((rtx *, rtx *, enum rtx_code *, rtx,
                                      enum machine_mode *, int *, int,
@@ -885,6 +897,7 @@ extern rtx gen_cond_trap PARAMS ((enum rtx_code, rtx, rtx, rtx));
 /* Functions from builtins.c:  */
 #ifdef TREE_CODE
 extern rtx expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
+extern tree expand_tree_builtin PARAMS ((tree, tree, tree));
 extern void std_expand_builtin_va_start PARAMS ((int, tree, rtx));
 extern rtx std_expand_builtin_va_arg PARAMS ((tree, tree));
 extern rtx expand_builtin_va_arg PARAMS ((tree, tree));
index 667059c1dda38a9ea86c11f40f8650c8fc11e031..d07124462628033ced863ccc2a00ad51b88bb9ce 100644 (file)
@@ -1,23 +1,23 @@
 /* fp-test.c - Check that all floating-point operations are available.
-   Copyright (C) 1995 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2000 Free Software Foundation, Inc.
    Contributed by Ronald F. Guilmette <rfg@monkeys.com>.
 
-This file is part of GNU CC.
+   This file is part of GNU CC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+   GNU CC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   GNU CC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with GNU CC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 /* This is a trivial test program which may be useful to people who are
    porting the GCC or G++ compilers to a new system.  The intent here is
@@ -104,6 +104,13 @@ main ()
   si = f1 >= f2;
   si = f1 <= f2;
 
+  si = __builtin_isgreater (f1, f2);
+  si = __builtin_isgreaterequal (f1, f2);
+  si = __builtin_isless (f1, f2);
+  si = __builtin_islessequal (f1, f2);
+  si = __builtin_islessgreater (f1, f2);
+  si = __builtin_isunordered (f1, f2);
+
   sc = f1;
   uc = f1;
   ss = f1;
@@ -143,6 +150,13 @@ main ()
   si = d1 >= d2;
   si = d1 <= d2;
 
+  si = __builtin_isgreater (d1, d2);
+  si = __builtin_isgreaterequal (d1, d2);
+  si = __builtin_isless (d1, d2);
+  si = __builtin_islessequal (d1, d2);
+  si = __builtin_islessgreater (d1, d2);
+  si = __builtin_isunordered (d1, d2);
+
   sc = d1;
   uc = d1;
   ss = d1;
@@ -182,6 +196,13 @@ main ()
   si = D1 >= D2;
   si = D1 <= D2;
 
+  si = __builtin_isgreater (D1, D2);
+  si = __builtin_isgreaterequal (D1, D2);
+  si = __builtin_isless (D1, D2);
+  si = __builtin_islessequal (D1, D2);
+  si = __builtin_islessgreater (D1, D2);
+  si = __builtin_isunordered (D1, D2);
+
   sc = D1;
   uc = D1;
   ss = D1;
index bbd04da914ff1b4ea94c6f9d7bbf3d23c9bb62ea..bd22231fcfad0ea22a2f3bf3e828db2aa8b20b73 100644 (file)
@@ -3429,11 +3429,12 @@ can_reverse_comparison_p (comparison, insn)
              && GET_MODE_CLASS (GET_MODE (arg0)) != MODE_FLOAT));
 }
 
-/* Given an rtx-code for a comparison, return the code
-   for the negated comparison.
-   WATCH OUT!  reverse_condition is not safe to use on a jump
-   that might be acting on the results of an IEEE floating point comparison,
-   because of the special treatment of non-signaling nans in comparisons.  
+/* Given an rtx-code for a comparison, return the code for the negated
+   comparison.  If no such code exists, return UNKNOWN.
+
+   WATCH OUT!  reverse_condition is not safe to use on a jump that might
+   be acting on the results of an IEEE floating point comparison, because
+   of the special treatment of non-signaling nans in comparisons.  
    Use can_reverse_comparison_p to be sure.  */
 
 enum rtx_code
@@ -3444,37 +3445,39 @@ reverse_condition (code)
     {
     case EQ:
       return NE;
-
     case NE:
       return EQ;
-
     case GT:
       return LE;
-
     case GE:
       return LT;
-
     case LT:
       return GE;
-
     case LE:
       return GT;
-
     case GTU:
       return LEU;
-
     case GEU:
       return LTU;
-
     case LTU:
       return GEU;
-
     case LEU:
       return GTU;
+    case UNORDERED:
+      return ORDERED;
+    case ORDERED:
+      return UNORDERED;
+
+    case UNLT:
+    case UNLE:
+    case UNGT:
+    case UNGE:
+    case UNEQ:
+    case UNNE:
+      return UNKNOWN;
 
     default:
       abort ();
-      return UNKNOWN;
     }
 }
 
@@ -3489,35 +3492,40 @@ swap_condition (code)
     {
     case EQ:
     case NE:
+    case UNORDERED:
+    case ORDERED:
+    case UNEQ:
+    case UNNE:
       return code;
 
     case GT:
       return LT;
-
     case GE:
       return LE;
-
     case LT:
       return GT;
-
     case LE:
       return GE;
-
     case GTU:
       return LTU;
-
     case GEU:
       return LEU;
-
     case LTU:
       return GTU;
-
     case LEU:
       return GEU;
 
+    case UNLT:
+      return UNGT;
+    case UNLE:
+      return UNGE;
+    case UNGT:
+      return UNLT;
+    case UNGE:
+      return UNLE;
+
     default:
       abort ();
-      return UNKNOWN;
     }
 }
 
@@ -5272,10 +5280,11 @@ thread_jumps (f, max_reg, flag_before_loop)
          if (rtx_equal_for_thread_p (b1op0, b2op0, b2)
              && rtx_equal_for_thread_p (b1op1, b2op1, b2)
              && (comparison_dominates_p (code1, code2)
-                 || (comparison_dominates_p (code1, reverse_condition (code2))
-                     && can_reverse_comparison_p (XEXP (SET_SRC (PATTERN (b1)),
-                                                        0),
-                                                  b1))))
+                 || (can_reverse_comparison_p (XEXP (SET_SRC (PATTERN (b1)),
+                                                     0),
+                                               b1)
+                     && comparison_dominates_p (code1, reverse_condition (code2)))))
+
            {
              t1 = prev_nonnote_insn (b1);
              t2 = prev_nonnote_insn (b2);
index 936adfb96f1326271070eadb90240dc6189400dc..152f9cf2f1b8dbfe3341947b127be38c9cc75ddb 100644 (file)
@@ -9163,6 +9163,8 @@ get_condition (jump, earliest)
          if (reverse_code)
            {
              code = reverse_condition (code);
+             if (code == UNKNOWN)
+               return 0;
              did_reverse_condition ^= 1;
              reverse_code = 0;
            }
@@ -9227,9 +9229,10 @@ get_condition (jump, earliest)
     }
 
   /* If this was floating-point and we reversed anything other than an
-     EQ or NE, return zero.  */
+     EQ or NE or (UN)ORDERED, return zero.  */
   if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-      && did_reverse_condition && code != NE && code != EQ
+      && did_reverse_condition
+      && code != NE && code != EQ && code != UNORDERED && code != ORDERED
       && ! flag_fast_math
       && GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
     return 0;
index 14fd87e26d025bb3a7e3c843b25f5641c351c295..df08316a32559f31bcee3c777ea8f8dc36d69fd6 100644 (file)
@@ -2325,7 +2325,8 @@ expand_abs (mode, op0, target, safe)
 
   /* If this mode is an integer too wide to compare properly,
      compare word by word.  Rely on CSE to optimize constant cases.  */
-  if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode, ccp_jump))
+  if (GET_MODE_CLASS (mode) == MODE_INT
+      && ! can_compare_p (GE, mode, ccp_jump))
     do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx, 
                                  NULL_RTX, op1);
   else
@@ -2840,18 +2841,31 @@ emit_0_to_1_insn (x)
 }
 
 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
-   If FOR_JUMP is nonzero, we will be generating a jump based on this
-   comparison, otherwise a store-flags operation.  */
+   PURPOSE describes how this comparison will be used.  CODE is the rtx
+   comparison code we will be using.
+
+   ??? Actually, CODE is slightly weaker than that.  A target is still
+   required to implement all of the normal bcc operations, but not 
+   required to implement all (or any) of the unordered bcc operations.  */
   
 int
-can_compare_p (mode, purpose)
+can_compare_p (code, mode, purpose)
+     enum rtx_code code;
      enum machine_mode mode;
      enum can_compare_purpose purpose;
 {
   do
     {
       if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
-       return 1;
+       {
+         if (purpose == ccp_jump)
+           return bcc_gen_fctn[(int)code] != NULL;
+         else if (purpose == ccp_store_flag)
+           return setcc_gen_code[(int)code] != CODE_FOR_nothing;
+         else
+           /* There's only one cmov entry point, and it's allowed to fail.  */
+           return 1;
+       }
       if (purpose == ccp_jump
          && cbranch_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
        return 1;
@@ -3016,7 +3030,7 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align,
 
   *px = x;
   *py = y;
-  if (can_compare_p (mode, purpose))
+  if (can_compare_p (*pcomparison, mode, purpose))
     return;
 
   /* Handle a lib call just for the mode we are using.  */
@@ -3267,6 +3281,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
        libfunc = lehf2_libfunc;
        break;
 
+      case UNORDERED:
+       libfunc = unordhf2_libfunc;
+       break;
+
       default:
        break;
       }
@@ -3297,6 +3315,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
        libfunc = lesf2_libfunc;
        break;
 
+      case UNORDERED:
+       libfunc = unordsf2_libfunc;
+       break;
+
       default:
        break;
       }
@@ -3327,6 +3349,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
        libfunc = ledf2_libfunc;
        break;
 
+      case UNORDERED:
+       libfunc = unorddf2_libfunc;
+       break;
+
       default:
        break;
       }
@@ -3357,6 +3383,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
        libfunc = lexf2_libfunc;
        break;
 
+      case UNORDERED:
+       libfunc = unordxf2_libfunc;
+       break;
+
       default:
        break;
       }
@@ -3387,6 +3417,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
        libfunc = letf2_libfunc;
        break;
 
+      case UNORDERED:
+       libfunc = unordtf2_libfunc;
+       break;
+
       default:
        break;
       }
@@ -3415,8 +3449,7 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
   if (libfunc == 0)
     abort ();
 
-  emit_library_call (libfunc, 1,
-                    word_mode, 2, x, mode, y, mode);
+  emit_library_call (libfunc, 1, word_mode, 2, x, mode, y, mode);
 
   /* Immediately move the result of the libcall into a pseudo
      register so reload doesn't clobber the value if it needs
@@ -3426,8 +3459,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
   *px = result;
   *py = const0_rtx;
   *pmode = word_mode;
+  if (comparison == UNORDERED)
+    *pcomparison = NE;
 #ifdef FLOAT_LIB_COMPARE_RETURNS_BOOL
-  if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
+  else if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
     *pcomparison = NE;
 #endif
   *punsignedp = 0;
@@ -4650,6 +4685,7 @@ init_optabs ()
   gehf2_libfunc = init_one_libfunc ("__gehf2");
   lthf2_libfunc = init_one_libfunc ("__lthf2");
   lehf2_libfunc = init_one_libfunc ("__lehf2");
+  unordhf2_libfunc = init_one_libfunc ("__unordhf2");
 
   eqsf2_libfunc = init_one_libfunc ("__eqsf2");
   nesf2_libfunc = init_one_libfunc ("__nesf2");
@@ -4657,6 +4693,7 @@ init_optabs ()
   gesf2_libfunc = init_one_libfunc ("__gesf2");
   ltsf2_libfunc = init_one_libfunc ("__ltsf2");
   lesf2_libfunc = init_one_libfunc ("__lesf2");
+  unordsf2_libfunc = init_one_libfunc ("__unordsf2");
 
   eqdf2_libfunc = init_one_libfunc ("__eqdf2");
   nedf2_libfunc = init_one_libfunc ("__nedf2");
@@ -4664,6 +4701,7 @@ init_optabs ()
   gedf2_libfunc = init_one_libfunc ("__gedf2");
   ltdf2_libfunc = init_one_libfunc ("__ltdf2");
   ledf2_libfunc = init_one_libfunc ("__ledf2");
+  unorddf2_libfunc = init_one_libfunc ("__unorddf2");
 
   eqxf2_libfunc = init_one_libfunc ("__eqxf2");
   nexf2_libfunc = init_one_libfunc ("__nexf2");
@@ -4671,6 +4709,7 @@ init_optabs ()
   gexf2_libfunc = init_one_libfunc ("__gexf2");
   ltxf2_libfunc = init_one_libfunc ("__ltxf2");
   lexf2_libfunc = init_one_libfunc ("__lexf2");
+  unordxf2_libfunc = init_one_libfunc ("__unordxf2");
 
   eqtf2_libfunc = init_one_libfunc ("__eqtf2");
   netf2_libfunc = init_one_libfunc ("__netf2");
@@ -4678,6 +4717,7 @@ init_optabs ()
   getf2_libfunc = init_one_libfunc ("__getf2");
   lttf2_libfunc = init_one_libfunc ("__lttf2");
   letf2_libfunc = init_one_libfunc ("__letf2");
+  unordtf2_libfunc = init_one_libfunc ("__unordtf2");
 
   floatsisf_libfunc = init_one_libfunc ("__floatsisf");
   floatdisf_libfunc = init_one_libfunc ("__floatdisf");
index 2c323fc823950262cfadf78bf25694524c32bb0a..94b72b810d21450fe659d8c674b09e3437579ffb 100644 (file)
@@ -737,6 +737,18 @@ DEF_RTL_EXPR(GTU, "gtu", "ee", '<')
 DEF_RTL_EXPR(LEU, "leu", "ee", '<')
 DEF_RTL_EXPR(LTU, "ltu", "ee", '<')
 
+/* Additional floating point unordered comparision flavors.  */
+DEF_RTL_EXPR(UNORDERED, "unordered", "ee", '<')
+DEF_RTL_EXPR(ORDERED, "ordered", "ee", '<')
+
+/* These are equivalent to unordered or ... */
+DEF_RTL_EXPR(UNNE, "unne", "ee", '<')
+DEF_RTL_EXPR(UNEQ, "uneq", "ee", '<')
+DEF_RTL_EXPR(UNGE, "unge", "ee", '<')
+DEF_RTL_EXPR(UNGT, "ungt", "ee", '<')
+DEF_RTL_EXPR(UNLE, "unle", "ee", '<')
+DEF_RTL_EXPR(UNLT, "unlt", "ee", '<')
+
 /* Represents the result of sign-extending the sole operand.
    The machine modes of the operand and of the SIGN_EXTEND expression
    determine how much sign-extension is going on.  */
index fca36560a4929d281339847dd75d4dbb24617ea6..20813131cc5b21d03fbe95a6b455822bd2849b23 100644 (file)
@@ -1,3 +1,7 @@
+2000-01-24  Richard Henderson  <rth@cygnus.com>
+
+       * gcc.c-torture/execute/ieee/fp-cmp-4.c: New.
+
 Thu Jan 20 12:34:48 2000  Jeffrey A Law  (law@cygnus.com)
 
        * gcc.c-torture/execute/20000120-2.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-4.c b/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-4.c
new file mode 100644 (file)
index 0000000..80342ee
--- /dev/null
@@ -0,0 +1,131 @@
+void
+test_isunordered(double x, double y, int true)
+{
+  if (__builtin_isunordered(x, y))
+    {
+      if (! true)
+       abort ();
+    }
+  else
+    {
+      if (true)
+       abort ();
+    }
+}
+
+void
+test_isless(double x, double y, int true)
+{
+  if (__builtin_isless(x, y))
+    {
+      if (! true)
+       abort ();
+    }
+  else
+    {
+      if (true)
+       abort ();
+    }
+}
+
+void
+test_islessequal(double x, double y, int true)
+{
+  if (__builtin_islessequal(x, y))
+    {
+      if (! true)
+       abort ();
+    }
+  else
+    {
+      if (true)
+       abort ();
+    }
+}
+
+void
+test_isgreater(double x, double y, int true)
+{
+  if (__builtin_isgreater(x, y))
+    {
+      if (! true)
+       abort ();
+    }
+  else
+    {
+      if (true)
+       abort ();
+    }
+}
+
+void
+test_isgreaterequal(double x, double y, int true)
+{
+  if (__builtin_isgreaterequal(x, y))
+    {
+      if (! true)
+       abort ();
+    }
+  else
+    {
+      if (true)
+       abort ();
+    }
+}
+
+void
+test_islessgreater(double x, double y, int true)
+{
+  if (__builtin_islessgreater(x, y))
+    {
+      if (! true)
+       abort ();
+    }
+  else
+    {
+      if (true)
+       abort ();
+    }
+}
+
+#define NAN (0.0 / 0.0)
+
+int
+main()
+{
+  struct try
+  {
+    double x, y;
+    unsigned unord : 1;
+    unsigned lt : 1;
+    unsigned le : 1;
+    unsigned gt : 1;
+    unsigned ge : 1;
+    unsigned lg : 1;
+  };
+
+  const struct try data[] =
+  {
+    { NAN, NAN, 1, 0, 0, 0, 0, 0 },
+    { 0.0, NAN, 1, 0, 0, 0, 0, 0 },
+    { NAN, 0.0, 1, 0, 0, 0, 0, 0 },
+    { 0.0, 0.0, 0, 0, 1, 0, 1, 0 },
+    { 1.0, 2.0, 0, 1, 1, 0, 0, 1 },
+    { 2.0, 1.0, 0, 0, 0, 1, 1, 1 },
+  };
+
+  const int n = sizeof(data) / sizeof(data[0]);
+  int i;
+
+  for (i = 0; i < n; ++i)
+    {
+      test_isunordered (data[i].x, data[i].y, data[i].unord);
+      test_isless (data[i].x, data[i].y, data[i].lt);
+      test_islessequal (data[i].x, data[i].y, data[i].le);
+      test_isgreater (data[i].x, data[i].y, data[i].gt);
+      test_isgreaterequal (data[i].x, data[i].y, data[i].ge);
+      test_islessgreater (data[i].x, data[i].y, data[i].lg);
+    }
+
+  exit (0);
+}
index 2ba6f2de1d7d1d134690dffdfec1212abb73744c..b4fb3cac6a123239a2dbadd6b3bc9fc4a90ba131 100644 (file)
@@ -641,6 +641,18 @@ DEFTREECODE (GE_EXPR, "ge_expr", '<', 2)
 DEFTREECODE (EQ_EXPR, "eq_expr", '<', 2)
 DEFTREECODE (NE_EXPR, "ne_expr", '<', 2)
 
+/* Additional relational operators for floating point unordered.  */
+DEFTREECODE (UNORDERED_EXPR, "unordered_expr", '<', 2)
+DEFTREECODE (ORDERED_EXPR, "ordered_expr", '<', 2)
+
+/* These are equivalent to unordered or ... */
+DEFTREECODE (UNLT_EXPR, "unlt_expr", '<', 2)
+DEFTREECODE (UNLE_EXPR, "unle_expr", '<', 2)
+DEFTREECODE (UNGT_EXPR, "ungt_expr", '<', 2)
+DEFTREECODE (UNGE_EXPR, "unge_expr", '<', 2)
+DEFTREECODE (UNEQ_EXPR, "uneq_expr", '<', 2)
+DEFTREECODE (UNNE_EXPR, "unne_expr", '<', 2)
+
 /* Operations for Pascal sets.  Not used now.  */
 DEFTREECODE (IN_EXPR, "in_expr", '2', 2)
 DEFTREECODE (SET_LE_EXPR, "set_le_expr", '<', 2)
index 84a333de367a17b75d065ad9f78839c11c56a3e2..d6e51a0e485a739811589624191ee88527ca576e 100644 (file)
@@ -116,6 +116,14 @@ enum built_in_function
   BUILT_IN_LONGJMP,
   BUILT_IN_TRAP,
 
+  /* ISO C99 floating point unordered comparisons.  */
+  BUILT_IN_ISGREATER,
+  BUILT_IN_ISGREATEREQUAL,
+  BUILT_IN_ISLESS,
+  BUILT_IN_ISLESSEQUAL,
+  BUILT_IN_ISLESSGREATER,
+  BUILT_IN_ISUNORDERED,
+
   /* Various hooks for the DWARF 2 __throw routine.  */
   BUILT_IN_UNWIND_INIT,
   BUILT_IN_DWARF_CFA,