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/expr.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/expr.c')
-rw-r--r-- | gcc/expr.c | 129 |
1 files changed, 120 insertions, 9 deletions
@@ -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)) |