aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@gcc.gnu.org>2000-01-24 12:10:04 -0800
committerRichard Henderson <rth@gcc.gnu.org>2000-01-24 12:10:04 -0800
commit1eb8759b1bc0fd2a74ddbd83db1f01df1a35df69 (patch)
treea9f7967b844ec94122754eade0945e4f551bf9f1 /gcc/optabs.c
parentd6cde8451a650824fcf971d56978b50d949aa3a2 (diff)
downloadgcc-1eb8759b1bc0fd2a74ddbd83db1f01df1a35df69.zip
gcc-1eb8759b1bc0fd2a74ddbd83db1f01df1a35df69.tar.gz
gcc-1eb8759b1bc0fd2a74ddbd83db1f01df1a35df69.tar.bz2
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
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 14fd87e..df08316 100644
--- a/gcc/optabs.c
+++ b/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");