diff options
author | Richard Henderson <rth@gcc.gnu.org> | 2000-01-24 12:10:04 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2000-01-24 12:10:04 -0800 |
commit | 1eb8759b1bc0fd2a74ddbd83db1f01df1a35df69 (patch) | |
tree | a9f7967b844ec94122754eade0945e4f551bf9f1 /gcc/optabs.c | |
parent | d6cde8451a650824fcf971d56978b50d949aa3a2 (diff) | |
download | gcc-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.c | 58 |
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"); |