rtl.def: Add unordered fp comparisions.
* 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
This commit is contained in:
parent
d6cde8451a
commit
1eb8759b1b
27 changed files with 800 additions and 193 deletions
103
gcc/ChangeLog
103
gcc/ChangeLog
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
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);
|
||||
}
|
||||
TREE_SIDE_EFFECTS (result) = 1;
|
||||
if (TREE_TYPE (result) == void_type_node)
|
||||
return result;
|
||||
return require_complete_type (result);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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}}, \
|
||||
|
|
|
@ -2752,12 +2752,12 @@
|
|||
"")
|
||||
|
||||
;; 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"
|
||||
|
@ -2765,9 +2765,9 @@
|
|||
[(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"
|
||||
|
@ -2777,7 +2777,7 @@
|
|||
|
||||
(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")]))]
|
||||
|
@ -2788,7 +2788,7 @@
|
|||
|
||||
(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")]))]
|
||||
|
@ -2799,7 +2799,7 @@
|
|||
|
||||
(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"))]))]
|
||||
|
@ -2810,7 +2810,7 @@
|
|||
|
||||
(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"))]))]
|
||||
|
@ -2821,7 +2821,7 @@
|
|||
|
||||
(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
|
||||
|
@ -2833,7 +2833,7 @@
|
|||
|
||||
(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
|
||||
|
@ -3126,6 +3126,22 @@
|
|||
""
|
||||
"{ 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))]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
@ -111,10 +117,10 @@
|
|||
|
||||
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>
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
10
gcc/cse.c
10
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. */
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
129
gcc/expr.c
129
gcc/expr.c
|
@ -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))
|
||||
|
|
15
gcc/expr.h
15
gcc/expr.h
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
63
gcc/jump.c
63
gcc/jump.c
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
58
gcc/optabs.c
58
gcc/optabs.c
|
@ -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");
|
||||
|
|
12
gcc/rtl.def
12
gcc/rtl.def
|
@ -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. */
|
||||
|
|
|
@ -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.
|
||||
|
|
131
gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-4.c
Normal file
131
gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-4.c
Normal file
|
@ -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);
|
||||
}
|
12
gcc/tree.def
12
gcc/tree.def
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue