From: bonzini Date: Sun, 28 Jun 2009 17:06:11 +0000 (+0000) Subject: 2009-06-28 Paolo Bonzini X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=e6a0a4a315e62e4f20908121db6bc452e393491a 2009-06-28 Paolo Bonzini * config/i386/i386.h (enum ix86_fpcmp_strategy): New. * config/i386/i386.md (cbranchxf4, cstorexf4, cbranch4, cstore4, movcc): Change predicate to ix86_fp_comparison_operator. (*fp_jcc_1_mixed, *fp_jcc_1_sse, *fp_jcc_1_387, *fp_jcc_2_mixed, *fp_jcc_2_sse, *fp_jcc_2_387): Delete (*fp_jcc_3_387, *fp_jcc_4_387, *fp_jcc_5_387, *fp_jcc_6_387, *fp_jcc_7_387, *fp_jcc_8_387): Eliminate call to !ix86_use_fcomi_compare, change ix86_fp_jump_nontrivial_p call to !TARGET_CMOVE, change predicate to ix86_fp_comparison_operator. (related splits): Change predicate to ix86_fp_comparison_operator. * config/i386/predicates.md: Use ix86_trivial_fp_comparison_operator instead of ix86_fp_comparison_codes. (ix86_trivial_fp_comparison_operator, ix86_fp_comparison_operator): New. * config/i386/i386-protos.h (ix86_fp_comparison_strategy): New. (ix86_expand_compare): Eliminate last two parameters. (ix86_fp_jump_nontrivial_p): Kill. * config/i386/i386.c (put_condition_code): Eliminate call to ix86_fp_comparison_codes and subsequent assertion. (ix86_fp_comparison_codes): Eliminate. (ix86_fp_swap_condition): New. (ix86_fp_comparison_arithmetics_cost, ix86_fp_comparison_fcomi_cost, ix86_fp_comparison_sahf_cost, ix86_use_fcomi_compare): Consolidate into ix86_fp_comparison_cost and ix86_fp_comparison_strategy. (ix86_prepare_fp_compare_args): Use ix86_fp_comparison_strategy and ix86_fp_swap_condition. (ix86_expand_fp_compare): Eliminate code for second jump/bypass jump. Use ix86_fp_comparison_strategy. (ix86_expand_compare): Likewise. Eliminate last two arguments. (ix86_fp_jump_nontrivial_p): Eliminate. (ix86_expand_branch): Treat SFmode/DFmode/XFmode as simple. Adjust call to ix86_expand_compare. (ix86_split_fp_branch, ix86_expand_setcc, ix86_expand_carry_flag_compare, ix86_expand_int_movcc, ix86_expand_fp_movcc): Eliminate code for second jump/bypass jump. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@149035 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index db35ccf4bc5..436ea0dca72 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,44 @@ 2009-06-28 Paolo Bonzini + * config/i386/i386.h (enum ix86_fpcmp_strategy): New. + * config/i386/i386.md (cbranchxf4, cstorexf4, cbranch4, + cstore4, movcc): Change predicate to + ix86_fp_comparison_operator. + (*fp_jcc_1_mixed, *fp_jcc_1_sse, *fp_jcc_1_387, *fp_jcc_2_mixed, + *fp_jcc_2_sse, *fp_jcc_2_387): Delete + (*fp_jcc_3_387, *fp_jcc_4_387, *fp_jcc_5_387, *fp_jcc_6_387, + *fp_jcc_7_387, *fp_jcc_8_387): Eliminate call to + !ix86_use_fcomi_compare, change ix86_fp_jump_nontrivial_p call + to !TARGET_CMOVE, change predicate to ix86_fp_comparison_operator. + (related splits): Change predicate to ix86_fp_comparison_operator. + * config/i386/predicates.md: Use ix86_trivial_fp_comparison_operator + instead of ix86_fp_comparison_codes. + (ix86_trivial_fp_comparison_operator, + ix86_fp_comparison_operator): New. + * config/i386/i386-protos.h (ix86_fp_comparison_strategy): New. + (ix86_expand_compare): Eliminate last two parameters. + (ix86_fp_jump_nontrivial_p): Kill. + * config/i386/i386.c (put_condition_code): Eliminate call to + ix86_fp_comparison_codes and subsequent assertion. + (ix86_fp_comparison_codes): Eliminate. + (ix86_fp_swap_condition): New. + (ix86_fp_comparison_arithmetics_cost, ix86_fp_comparison_fcomi_cost, + ix86_fp_comparison_sahf_cost, ix86_use_fcomi_compare): Consolidate + into ix86_fp_comparison_cost and ix86_fp_comparison_strategy. + (ix86_prepare_fp_compare_args): Use ix86_fp_comparison_strategy + and ix86_fp_swap_condition. + (ix86_expand_fp_compare): Eliminate code for second jump/bypass jump. + Use ix86_fp_comparison_strategy. + (ix86_expand_compare): Likewise. Eliminate last two arguments. + (ix86_fp_jump_nontrivial_p): Eliminate. + (ix86_expand_branch): Treat SFmode/DFmode/XFmode as simple. Adjust + call to ix86_expand_compare. + (ix86_split_fp_branch, ix86_expand_setcc, + ix86_expand_carry_flag_compare, ix86_expand_int_movcc, + ix86_expand_fp_movcc): Eliminate code for second jump/bypass jump. + +2009-06-28 Paolo Bonzini + * config/arm/arm.c (arm_final_prescan_ins): Eliminate code related to jump_clobbers. * config/arm/arm.md (conds): Remove jump_clob case. diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 8ae5bd66b26..663b4bffacc 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -95,6 +95,7 @@ extern void ix86_expand_convert_uns_sixf_sse (rtx, rtx); extern void ix86_expand_convert_uns_sidf_sse (rtx, rtx); extern void ix86_expand_convert_uns_sisf_sse (rtx, rtx); extern void ix86_expand_convert_sign_didf_sse (rtx, rtx); +extern enum ix86_fpcmp_strategy ix86_fp_comparison_strategy (enum rtx_code); extern void ix86_expand_fp_absneg_operator (enum rtx_code, enum machine_mode, rtx[]); extern void ix86_expand_copysign (rtx []); @@ -102,7 +103,7 @@ extern void ix86_split_copysign_const (rtx []); extern void ix86_split_copysign_var (rtx []); extern int ix86_unary_operator_ok (enum rtx_code, enum machine_mode, rtx[]); extern int ix86_match_ccmode (rtx, enum machine_mode); -extern rtx ix86_expand_compare (enum rtx_code, rtx *, rtx *); +extern rtx ix86_expand_compare (enum rtx_code); extern int ix86_use_fcomi_compare (enum rtx_code); extern void ix86_expand_branch (enum rtx_code, rtx); extern void ix86_expand_setcc (enum rtx_code, rtx); @@ -162,7 +163,6 @@ extern enum reg_class ix86_preferred_output_reload_class (rtx, enum reg_class); extern int ix86_memory_move_cost (enum machine_mode, enum reg_class, int); extern int ix86_mode_needed (int, rtx); extern void emit_i387_cw_initialization (int); -extern bool ix86_fp_jump_nontrivial_p (enum rtx_code); extern void x86_order_regs_for_local_alloc (void); extern void x86_function_profiler (FILE *, int); extern void x86_emit_floatuns (rtx [2]); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 06ae734af30..81f3b9eb44b 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10838,9 +10838,6 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, int reverse, if (mode == CCFPmode || mode == CCFPUmode) { - enum rtx_code second_code, bypass_code; - ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code); - gcc_assert (bypass_code == UNKNOWN && second_code == UNKNOWN); code = ix86_fp_compare_code_to_integer (code); mode = CCmode; } @@ -14465,84 +14462,41 @@ ix86_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2) } } -/* Split comparison code CODE into comparisons we can do using branch - instructions. BYPASS_CODE is comparison code for branch that will - branch around FIRST_CODE and SECOND_CODE. If some of branches - is not required, set value to UNKNOWN. - We never require more than two branches. */ -void -ix86_fp_comparison_codes (enum rtx_code code, enum rtx_code *bypass_code, - enum rtx_code *first_code, - enum rtx_code *second_code) -{ - *first_code = code; - *bypass_code = UNKNOWN; - *second_code = UNKNOWN; - - /* The fcomi comparison sets flags as follows: - - cmp ZF PF CF - > 0 0 0 - < 0 0 1 - = 1 0 0 - un 1 1 1 */ +/* Return a comparison we can do and that it is equivalent to + swap_condition (code) apart possibly from orderedness. + But, never change orderedness if TARGET_IEEE_FP, returning + UNKNOWN in that case if necessary. */ +static enum rtx_code +ix86_fp_swap_condition (enum rtx_code code) +{ switch (code) { - case GT: /* GTU - CF=0 & ZF=0 */ - case GE: /* GEU - CF=0 */ - case ORDERED: /* PF=0 */ - case UNORDERED: /* PF=1 */ - case UNEQ: /* EQ - ZF=1 */ - case UNLT: /* LTU - CF=1 */ - case UNLE: /* LEU - CF=1 | ZF=1 */ - case LTGT: /* EQ - ZF=0 */ - break; - case LT: /* LTU - CF=1 - fails on unordered */ - *first_code = UNLT; - *bypass_code = UNORDERED; - break; - case LE: /* LEU - CF=1 | ZF=1 - fails on unordered */ - *first_code = UNLE; - *bypass_code = UNORDERED; - break; - case EQ: /* EQ - ZF=1 - fails on unordered */ - *first_code = UNEQ; - *bypass_code = UNORDERED; - break; - case NE: /* NE - ZF=0 - fails on unordered */ - *first_code = LTGT; - *second_code = UNORDERED; - break; - case UNGE: /* GEU - CF=0 - fails on unordered */ - *first_code = GE; - *second_code = UNORDERED; - break; - case UNGT: /* GTU - CF=0 & ZF=0 - fails on unordered */ - *first_code = GT; - *second_code = UNORDERED; - break; + case GT: /* GTU - CF=0 & ZF=0 */ + return TARGET_IEEE_FP ? UNKNOWN : UNLT; + case GE: /* GEU - CF=0 */ + return TARGET_IEEE_FP ? UNKNOWN : UNLE; + case UNLT: /* LTU - CF=1 */ + return TARGET_IEEE_FP ? UNKNOWN : GT; + case UNLE: /* LEU - CF=1 | ZF=1 */ + return TARGET_IEEE_FP ? UNKNOWN : GE; default: - gcc_unreachable (); - } - if (!TARGET_IEEE_FP) - { - *second_code = UNKNOWN; - *bypass_code = UNKNOWN; + return swap_condition (code); } } -/* Return cost of comparison done fcom + arithmetics operations on AX. +/* Return cost of comparison CODE using the best strategy for performance. All following functions do use number of instructions as a cost metrics. In future this should be tweaked to compute bytes for optimize_size and take into account performance of various instructions on various CPUs. */ + static int -ix86_fp_comparison_arithmetics_cost (enum rtx_code code) +ix86_fp_comparison_cost (enum rtx_code code) { - if (!TARGET_IEEE_FP) - return 4; - /* The cost of code output by ix86_expand_fp_compare. */ + int arith_cost; + + /* The cost of code using bit-twiddling on %ah. */ switch (code) { case UNLE: @@ -14553,82 +14507,49 @@ ix86_fp_comparison_arithmetics_cost (enum rtx_code code) case UNORDERED: case ORDERED: case UNEQ: - return 4; + arith_cost = 4; break; case LT: case NE: case EQ: case UNGE: - return 5; + arith_cost = TARGET_IEEE_FP ? 5 : 4; break; case LE: case UNGT: - return 6; + arith_cost = TARGET_IEEE_FP ? 6 : 4; break; default: gcc_unreachable (); } -} -/* Return cost of comparison done using fcomi operation. - See ix86_fp_comparison_arithmetics_cost for the metrics. */ -static int -ix86_fp_comparison_fcomi_cost (enum rtx_code code) -{ - enum rtx_code bypass_code, first_code, second_code; - /* Return arbitrarily high cost when instruction is not supported - this - prevents gcc from using it. */ - if (!TARGET_CMOVE) - return 1024; - ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code); - return (bypass_code != UNKNOWN || second_code != UNKNOWN) + 2; + switch (ix86_fp_comparison_strategy (code)) + { + case IX86_FPCMP_COMI: + return arith_cost > 4 ? 3 : 2; + case IX86_FPCMP_SAHF: + return arith_cost > 4 ? 4 : 3; + default: + return arith_cost; + } } -/* Return cost of comparison done using sahf operation. - See ix86_fp_comparison_arithmetics_cost for the metrics. */ -static int -ix86_fp_comparison_sahf_cost (enum rtx_code code) -{ - enum rtx_code bypass_code, first_code, second_code; - /* Return arbitrarily high cost when instruction is not preferred - this - avoids gcc from using it. */ - if (!(TARGET_SAHF && (TARGET_USE_SAHF || optimize_insn_for_size_p ()))) - return 1024; - ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code); - return (bypass_code != UNKNOWN || second_code != UNKNOWN) + 3; -} +/* Return strategy to use for floating-point. We assume that fcomi is always + preferrable where available, since that is also true when looking at size + (2 bytes, vs. 3 for fnstsw+sahf and at least 5 for fnstsw+test). */ -/* Compute cost of the comparison done using any method. - See ix86_fp_comparison_arithmetics_cost for the metrics. */ -static int -ix86_fp_comparison_cost (enum rtx_code code) +enum ix86_fpcmp_strategy +ix86_fp_comparison_strategy (enum rtx_code code ATTRIBUTE_UNUSED) { - int fcomi_cost, sahf_cost, arithmetics_cost = 1024; - int min; - - fcomi_cost = ix86_fp_comparison_fcomi_cost (code); - sahf_cost = ix86_fp_comparison_sahf_cost (code); - - min = arithmetics_cost = ix86_fp_comparison_arithmetics_cost (code); - if (min > sahf_cost) - min = sahf_cost; - if (min > fcomi_cost) - min = fcomi_cost; - return min; -} + /* Do fcomi/sahf based test when profitable. */ -/* Return true if we should use an FCOMI instruction for this - fp comparison. */ + if (TARGET_CMOVE) + return IX86_FPCMP_COMI; -int -ix86_use_fcomi_compare (enum rtx_code code ATTRIBUTE_UNUSED) -{ - enum rtx_code swapped_code = swap_condition (code); + if (TARGET_SAHF && (TARGET_USE_SAHF || optimize_insn_for_size_p ())) + return IX86_FPCMP_SAHF; - return ((ix86_fp_comparison_cost (code) - == ix86_fp_comparison_fcomi_cost (code)) - || (ix86_fp_comparison_cost (swapped_code) - == ix86_fp_comparison_fcomi_cost (swapped_code))); + return IX86_FPCMP_ARITH; } /* Swap, force into registers, or otherwise massage the two operands @@ -14655,7 +14576,7 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1) && ! (standard_80387_constant_p (op0) == 1 || standard_80387_constant_p (op1) == 1) && GET_CODE (op1) != FLOAT) - || ix86_use_fcomi_compare (code))) + || ix86_fp_comparison_strategy (code) == IX86_FPCMP_COMI)) { op0 = force_reg (op_mode, op0); op1 = force_reg (op_mode, op1); @@ -14671,9 +14592,13 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1) && ! (standard_80387_constant_p (op1) == 0 || MEM_P (op1)))) { - rtx tmp; - tmp = op0, op0 = op1, op1 = tmp; - code = swap_condition (code); + enum rtx_code new_code = ix86_fp_swap_condition (code); + if (new_code != UNKNOWN) + { + rtx tmp; + tmp = op0, op0 = op1, op1 = tmp; + code = new_code; + } } if (!REG_P (op0)) @@ -14748,59 +14673,38 @@ ix86_fp_compare_code_to_integer (enum rtx_code code) /* Generate insn patterns to do a floating point compare of OPERANDS. */ static rtx -ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch, - rtx *second_test, rtx *bypass_test) +ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch) { enum machine_mode fpcmp_mode, intcmp_mode; rtx tmp, tmp2; - int cost = ix86_fp_comparison_cost (code); - enum rtx_code bypass_code, first_code, second_code; fpcmp_mode = ix86_fp_compare_mode (code); code = ix86_prepare_fp_compare_args (code, &op0, &op1); - if (second_test) - *second_test = NULL_RTX; - if (bypass_test) - *bypass_test = NULL_RTX; - - ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code); - /* Do fcomi/sahf based test when profitable. */ - if (ix86_fp_comparison_arithmetics_cost (code) > cost - && (bypass_code == UNKNOWN || bypass_test) - && (second_code == UNKNOWN || second_test)) + switch (ix86_fp_comparison_strategy (code)) { + case IX86_FPCMP_COMI: + intcmp_mode = fpcmp_mode; tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); tmp = gen_rtx_SET (VOIDmode, gen_rtx_REG (fpcmp_mode, FLAGS_REG), tmp); - if (TARGET_CMOVE) - emit_insn (tmp); - else - { - gcc_assert (TARGET_SAHF); + emit_insn (tmp); + break; - if (!scratch) - scratch = gen_reg_rtx (HImode); - tmp2 = gen_rtx_CLOBBER (VOIDmode, scratch); + case IX86_FPCMP_SAHF: + intcmp_mode = fpcmp_mode; + tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); + tmp = gen_rtx_SET (VOIDmode, gen_rtx_REG (fpcmp_mode, FLAGS_REG), + tmp); - emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, tmp2))); - } + if (!scratch) + scratch = gen_reg_rtx (HImode); + tmp2 = gen_rtx_CLOBBER (VOIDmode, scratch); + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, tmp2))); + break; - /* The FP codes work out to act like unsigned. */ - intcmp_mode = fpcmp_mode; - code = first_code; - if (bypass_code != UNKNOWN) - *bypass_test = gen_rtx_fmt_ee (bypass_code, VOIDmode, - gen_rtx_REG (intcmp_mode, FLAGS_REG), - const0_rtx); - if (second_code != UNKNOWN) - *second_test = gen_rtx_fmt_ee (second_code, VOIDmode, - gen_rtx_REG (intcmp_mode, FLAGS_REG), - const0_rtx); - } - else - { + case IX86_FPCMP_ARITH: /* Sadness wrt reg-stack pops killing fpsr -- gotta get fnstsw first. */ tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW); @@ -14922,6 +14826,10 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch, default: gcc_unreachable (); } + break; + + default: + gcc_unreachable(); } /* Return the test that should be put into the flags user, i.e. @@ -14932,25 +14840,19 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch, } rtx -ix86_expand_compare (enum rtx_code code, rtx *second_test, rtx *bypass_test) +ix86_expand_compare (enum rtx_code code) { rtx op0, op1, ret; op0 = ix86_compare_op0; op1 = ix86_compare_op1; - if (second_test) - *second_test = NULL_RTX; - if (bypass_test) - *bypass_test = NULL_RTX; - if (GET_MODE_CLASS (GET_MODE (ix86_compare_op0)) == MODE_CC) ret = gen_rtx_fmt_ee (code, VOIDmode, ix86_compare_op0, ix86_compare_op1); else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0))) { gcc_assert (!DECIMAL_FLOAT_MODE_P (GET_MODE (op0))); - ret = ix86_expand_fp_compare (code, op0, op1, NULL_RTX, - second_test, bypass_test); + ret = ix86_expand_fp_compare (code, op0, op1, NULL_RTX); } else ret = ix86_expand_int_compare (code, op0, op1); @@ -14958,17 +14860,6 @@ ix86_expand_compare (enum rtx_code code, rtx *second_test, rtx *bypass_test) return ret; } -/* Return true if the CODE will result in nontrivial jump sequence. */ -bool -ix86_fp_jump_nontrivial_p (enum rtx_code code) -{ - enum rtx_code bypass_code, first_code, second_code; - if (!TARGET_CMOVE) - return true; - ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code); - return bypass_code != UNKNOWN || second_code != UNKNOWN; -} - void ix86_expand_branch (enum rtx_code code, rtx label) { @@ -14976,64 +14867,20 @@ ix86_expand_branch (enum rtx_code code, rtx label) switch (GET_MODE (ix86_compare_op0)) { + case SFmode: + case DFmode: + case XFmode: case QImode: case HImode: case SImode: simple: - tmp = ix86_expand_compare (code, NULL, NULL); + tmp = ix86_expand_compare (code); tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); return; - case SFmode: - case DFmode: - case XFmode: - { - rtvec vec; - int use_fcomi; - enum rtx_code bypass_code, first_code, second_code; - - code = ix86_prepare_fp_compare_args (code, &ix86_compare_op0, - &ix86_compare_op1); - - ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code); - - /* Check whether we will use the natural sequence with one jump. If - so, we can expand jump early. Otherwise delay expansion by - creating compound insn to not confuse optimizers. */ - if (bypass_code == UNKNOWN && second_code == UNKNOWN) - { - ix86_split_fp_branch (code, ix86_compare_op0, ix86_compare_op1, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx, NULL_RTX, NULL_RTX); - } - else - { - tmp = gen_rtx_fmt_ee (code, VOIDmode, - ix86_compare_op0, ix86_compare_op1); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx); - tmp = gen_rtx_SET (VOIDmode, pc_rtx, tmp); - - use_fcomi = ix86_use_fcomi_compare (code); - vec = rtvec_alloc (3 + !use_fcomi); - RTVEC_ELT (vec, 0) = tmp; - RTVEC_ELT (vec, 1) - = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, FPSR_REG)); - RTVEC_ELT (vec, 2) - = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, FLAGS_REG)); - if (! use_fcomi) - RTVEC_ELT (vec, 3) - = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (HImode)); - - emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec)); - } - return; - } - case DImode: if (TARGET_64BIT) goto simple; @@ -15187,10 +15034,7 @@ void ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2, rtx target1, rtx target2, rtx tmp, rtx pushed) { - rtx second, bypass; - rtx label = NULL_RTX; rtx condition; - int bypass_probability = -1, second_probability = -1, probability = -1; rtx i; if (target2 != pc_rtx) @@ -15202,103 +15046,30 @@ ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2, } condition = ix86_expand_fp_compare (code, op1, op2, - tmp, &second, &bypass); + tmp); /* Remove pushed operand from stack. */ if (pushed) ix86_free_from_memory (GET_MODE (pushed)); - if (split_branch_probability >= 0) - { - /* Distribute the probabilities across the jumps. - Assume the BYPASS and SECOND to be always test - for UNORDERED. */ - probability = split_branch_probability; - - /* Value of 1 is low enough to make no need for probability - to be updated. Later we may run some experiments and see - if unordered values are more frequent in practice. */ - if (bypass) - bypass_probability = 1; - if (second) - second_probability = 1; - } - if (bypass != NULL_RTX) - { - label = gen_label_rtx (); - i = emit_jump_insn (gen_rtx_SET - (VOIDmode, pc_rtx, - gen_rtx_IF_THEN_ELSE (VOIDmode, - bypass, - gen_rtx_LABEL_REF (VOIDmode, - label), - pc_rtx))); - if (bypass_probability >= 0) - add_reg_note (i, REG_BR_PROB, GEN_INT (bypass_probability)); - } i = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, condition, target1, target2))); - if (probability >= 0) - add_reg_note (i, REG_BR_PROB, GEN_INT (probability)); - if (second != NULL_RTX) - { - i = emit_jump_insn (gen_rtx_SET - (VOIDmode, pc_rtx, - gen_rtx_IF_THEN_ELSE (VOIDmode, second, target1, - target2))); - if (second_probability >= 0) - add_reg_note (i, REG_BR_PROB, GEN_INT (second_probability)); - } - if (label != NULL_RTX) - emit_label (label); + if (split_branch_probability >= 0) + add_reg_note (i, REG_BR_PROB, GEN_INT (split_branch_probability)); } void ix86_expand_setcc (enum rtx_code code, rtx dest) { - rtx ret, tmp, tmpreg, equiv; - rtx second_test, bypass_test; + rtx ret; gcc_assert (GET_MODE (dest) == QImode); - ret = ix86_expand_compare (code, &second_test, &bypass_test); + ret = ix86_expand_compare (code); PUT_MODE (ret, QImode); - - tmp = dest; - tmpreg = dest; - - emit_insn (gen_rtx_SET (VOIDmode, tmp, ret)); - if (bypass_test || second_test) - { - rtx test = second_test; - int bypass = 0; - rtx tmp2 = gen_reg_rtx (QImode); - if (bypass_test) - { - gcc_assert (!second_test); - test = bypass_test; - bypass = 1; - PUT_CODE (test, reverse_condition_maybe_unordered (GET_CODE (test))); - } - PUT_MODE (test, QImode); - emit_insn (gen_rtx_SET (VOIDmode, tmp2, test)); - - if (bypass) - emit_insn (gen_andqi3 (tmp, tmpreg, tmp2)); - else - emit_insn (gen_iorqi3 (tmp, tmpreg, tmp2)); - } - - /* Attach a REG_EQUAL note describing the comparison result. */ - if (ix86_compare_op0 && ix86_compare_op1) - { - equiv = simplify_gen_relational (code, QImode, - GET_MODE (ix86_compare_op0), - ix86_compare_op0, ix86_compare_op1); - set_unique_reg_note (get_last_insn (), REG_EQUAL, equiv); - } + emit_insn (gen_rtx_SET (VOIDmode, dest, ret)); } /* Expand comparison setting or clearing carry flag. Return true when @@ -15315,7 +15086,6 @@ ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop) if (SCALAR_FLOAT_MODE_P (mode)) { - rtx second_test = NULL, bypass_test = NULL; rtx compare_op, compare_seq; gcc_assert (!DECIMAL_FLOAT_MODE_P (mode)); @@ -15341,14 +15111,10 @@ ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop) we decide to expand comparison using arithmetic that is not too common scenario. */ start_sequence (); - compare_op = ix86_expand_fp_compare (code, op0, op1, NULL_RTX, - &second_test, &bypass_test); + compare_op = ix86_expand_fp_compare (code, op0, op1, NULL_RTX); compare_seq = get_insns (); end_sequence (); - if (second_test || bypass_test) - return false; - if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode) code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op)); @@ -15431,7 +15197,7 @@ ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop) } ix86_compare_op0 = op0; ix86_compare_op1 = op1; - *pop = ix86_expand_compare (code, NULL, NULL); + *pop = ix86_expand_compare (code); gcc_assert (GET_CODE (*pop) == LTU || GET_CODE (*pop) == GEU); return true; } @@ -15441,14 +15207,13 @@ ix86_expand_int_movcc (rtx operands[]) { enum rtx_code code = GET_CODE (operands[1]), compare_code; rtx compare_seq, compare_op; - rtx second_test, bypass_test; enum machine_mode mode = GET_MODE (operands[0]); bool sign_bit_compare_p = false;; start_sequence (); ix86_compare_op0 = XEXP (operands[1], 0); ix86_compare_op1 = XEXP (operands[1], 1); - compare_op = ix86_expand_compare (code, &second_test, &bypass_test); + compare_op = ix86_expand_compare (code); compare_seq = get_insns (); end_sequence (); @@ -15920,19 +15685,6 @@ ix86_expand_int_movcc (rtx operands[]) if (! nonimmediate_operand (operands[3], mode)) operands[3] = force_reg (mode, operands[3]); - if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3])) - { - rtx tmp = gen_reg_rtx (mode); - emit_move_insn (tmp, operands[3]); - operands[3] = tmp; - } - if (second_test && reg_overlap_mentioned_p (operands[0], operands[2])) - { - rtx tmp = gen_reg_rtx (mode); - emit_move_insn (tmp, operands[2]); - operands[2] = tmp; - } - if (! register_operand (operands[2], VOIDmode) && (mode == QImode || ! register_operand (operands[3], VOIDmode))) @@ -15947,18 +15699,6 @@ ix86_expand_int_movcc (rtx operands[]) gen_rtx_IF_THEN_ELSE (mode, compare_op, operands[2], operands[3]))); - if (bypass_test) - emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (operands[0]), - gen_rtx_IF_THEN_ELSE (mode, - bypass_test, - copy_rtx (operands[3]), - copy_rtx (operands[0])))); - if (second_test) - emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (operands[0]), - gen_rtx_IF_THEN_ELSE (mode, - second_test, - copy_rtx (operands[2]), - copy_rtx (operands[0])))); return 1; /* DONE */ } @@ -16163,7 +15903,7 @@ ix86_expand_fp_movcc (rtx operands[]) { enum machine_mode mode = GET_MODE (operands[0]); enum rtx_code code = GET_CODE (operands[1]); - rtx tmp, compare_op, second_test, bypass_test; + rtx tmp, compare_op; ix86_compare_op0 = XEXP (operands[1], 0); ix86_compare_op1 = XEXP (operands[1], 1); @@ -16200,45 +15940,20 @@ ix86_expand_fp_movcc (rtx operands[]) /* The floating point conditional move instructions don't directly support conditions resulting from a signed integer comparison. */ - compare_op = ix86_expand_compare (code, &second_test, &bypass_test); - - /* The floating point conditional move instructions don't directly - support signed integer comparisons. */ - + compare_op = ix86_expand_compare (code); if (!fcmov_comparison_operator (compare_op, VOIDmode)) { - gcc_assert (!second_test && !bypass_test); tmp = gen_reg_rtx (QImode); ix86_expand_setcc (code, tmp); code = NE; ix86_compare_op0 = tmp; ix86_compare_op1 = const0_rtx; - compare_op = ix86_expand_compare (code, &second_test, &bypass_test); - } - if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3])) - { - tmp = gen_reg_rtx (mode); - emit_move_insn (tmp, operands[3]); - operands[3] = tmp; - } - if (second_test && reg_overlap_mentioned_p (operands[0], operands[2])) - { - tmp = gen_reg_rtx (mode); - emit_move_insn (tmp, operands[2]); - operands[2] = tmp; + compare_op = ix86_expand_compare (code); } emit_insn (gen_rtx_SET (VOIDmode, operands[0], gen_rtx_IF_THEN_ELSE (mode, compare_op, operands[2], operands[3]))); - if (bypass_test) - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_IF_THEN_ELSE (mode, bypass_test, - operands[3], operands[0]))); - if (second_test) - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_IF_THEN_ELSE (mode, second_test, - operands[2], operands[0]))); return 1; } diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 7592f6b420c..d762c29df94 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2308,6 +2308,12 @@ extern enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER]; extern rtx ix86_compare_op0; /* operand 0 for comparisons */ extern rtx ix86_compare_op1; /* operand 1 for comparisons */ + +enum ix86_fpcmp_strategy { + IX86_FPCMP_SAHF, + IX86_FPCMP_COMI, + IX86_FPCMP_ARITH +}; /* To properly truncate FP values into integers, we need to set i387 control word. We can't emit proper mode switching code before reload, as spills diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a71ca43c163..33ff7a5fd76 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1222,7 +1222,7 @@ (compare:CC (match_operand:XF 1 "nonmemory_operand" "") (match_operand:XF 2 "nonmemory_operand" ""))) (set (pc) (if_then_else - (match_operator 0 "comparison_operator" + (match_operator 0 "ix86_fp_comparison_operator" [(reg:CC FLAGS_REG) (const_int 0)]) (label_ref (match_operand 3 "" "")) @@ -1240,7 +1240,7 @@ (compare:CC (match_operand:XF 2 "nonmemory_operand" "") (match_operand:XF 3 "nonmemory_operand" ""))) (set (match_operand:QI 0 "register_operand" "") - (match_operator 1 "comparison_operator" + (match_operator 1 "ix86_fp_comparison_operator" [(reg:CC FLAGS_REG) (const_int 0)]))] "TARGET_80387" @@ -1256,7 +1256,7 @@ (compare:CC (match_operand:MODEF 1 "cmp_fp_expander_operand" "") (match_operand:MODEF 2 "cmp_fp_expander_operand" ""))) (set (pc) (if_then_else - (match_operator 0 "comparison_operator" + (match_operator 0 "ix86_fp_comparison_operator" [(reg:CC FLAGS_REG) (const_int 0)]) (label_ref (match_operand 3 "" "")) @@ -1274,7 +1274,7 @@ (compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand" "") (match_operand:MODEF 3 "cmp_fp_expander_operand" ""))) (set (match_operand:QI 0 "register_operand" "") - (match_operator 1 "comparison_operator" + (match_operator 1 "ix86_fp_comparison_operator" [(reg:CC FLAGS_REG) (const_int 0)]))] "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" @@ -15131,103 +15131,12 @@ (pc)))] "PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));") -;; Define combination compare-and-branch fp compare instructions to use -;; during early optimization. Splitting the operation apart early makes -;; for bad code when we want to reverse the operation. - -(define_insn "*fp_jcc_1_mixed" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f,x") - (match_operand 2 "nonimmediate_operand" "f,xm")]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "TARGET_MIX_SSE_I387 - && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") - -(define_insn "*fp_jcc_1_sse" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "x") - (match_operand 2 "nonimmediate_operand" "xm")]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "TARGET_SSE_MATH - && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") - -(define_insn "*fp_jcc_1_387" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f")]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "X87_FLOAT_MODE_P (GET_MODE (operands[1])) - && TARGET_CMOVE - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") - -(define_insn "*fp_jcc_2_mixed" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f,x") - (match_operand 2 "nonimmediate_operand" "f,xm")]) - (pc) - (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "TARGET_MIX_SSE_I387 - && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") - -(define_insn "*fp_jcc_2_sse" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "x") - (match_operand 2 "nonimmediate_operand" "xm")]) - (pc) - (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "TARGET_SSE_MATH - && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") - -(define_insn "*fp_jcc_2_387" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f")]) - (pc) - (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "X87_FLOAT_MODE_P (GET_MODE (operands[1])) - && TARGET_CMOVE - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") +;; Define combination compare-and-branch fp compare instructions to help +;; combine. (define_insn "*fp_jcc_3_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "nonimmediate_operand" "fm")]) (label_ref (match_operand 3 "" "")) @@ -15238,15 +15147,14 @@ "TARGET_80387 && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode) && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && !ix86_use_fcomi_compare (GET_CODE (operands[0])) && SELECT_CC_MODE (GET_CODE (operands[0]), operands[1], operands[2]) == CCFPmode - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + && !TARGET_CMOVE" "#") (define_insn "*fp_jcc_4_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "nonimmediate_operand" "fm")]) (pc) @@ -15257,15 +15165,14 @@ "TARGET_80387 && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode) && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && !ix86_use_fcomi_compare (GET_CODE (operands[0])) && SELECT_CC_MODE (GET_CODE (operands[0]), operands[1], operands[2]) == CCFPmode - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + && !TARGET_CMOVE" "#") (define_insn "*fp_jcc_5_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "register_operand" "f")]) (label_ref (match_operand 3 "" "")) @@ -15275,12 +15182,12 @@ (clobber (match_scratch:HI 4 "=a"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + && !TARGET_CMOVE" "#") (define_insn "*fp_jcc_6_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "register_operand" "f")]) (pc) @@ -15290,12 +15197,12 @@ (clobber (match_scratch:HI 4 "=a"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + && !TARGET_CMOVE" "#") (define_insn "*fp_jcc_7_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "const0_operand" "")]) (label_ref (match_operand 3 "" "")) @@ -15305,10 +15212,9 @@ (clobber (match_scratch:HI 4 "=a"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && !ix86_use_fcomi_compare (GET_CODE (operands[0])) && SELECT_CC_MODE (GET_CODE (operands[0]), operands[1], operands[2]) == CCFPmode - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + && !TARGET_CMOVE" "#") ;; The order of operands in *fp_jcc_8_387 is forced by combine in @@ -15318,7 +15224,7 @@ (define_insn "*fp_jcc_8_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operator 1 "float_operator" [(match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r")]) (match_operand 3 "register_operand" "f,f")]) @@ -15330,14 +15236,13 @@ "X87_FLOAT_MODE_P (GET_MODE (operands[3])) && (TARGET_USE_MODE_FIOP || optimize_function_for_size_p (cfun)) && GET_MODE (operands[1]) == GET_MODE (operands[3]) - && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0]))) && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode - && ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))" + && !TARGET_CMOVE" "#") (define_split [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "") (match_operand 2 "nonimmediate_operand" "")]) (match_operand 3 "" "") @@ -15354,7 +15259,7 @@ (define_split [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "") (match_operand 2 "general_operand" "")]) (match_operand 3 "" "") @@ -15372,7 +15277,7 @@ (define_split [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operator 1 "float_operator" [(match_operand:X87MODEI12 2 "memory_operand" "")]) (match_operand 3 "register_operand" "")]) @@ -15394,7 +15299,7 @@ ;; %%% Kill this when reload knows how to do it. (define_split [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operator 1 "float_operator" [(match_operand:X87MODEI12 2 "register_operand" "")]) (match_operand 3 "register_operand" "")]) @@ -20657,7 +20562,7 @@ (define_expand "movcc" [(set (match_operand:X87MODEF 0 "register_operand" "") (if_then_else:X87MODEF - (match_operand 1 "comparison_operator" "") + (match_operand 1 "ix86_fp_comparison_operator" "") (match_operand:X87MODEF 2 "register_operand" "") (match_operand:X87MODEF 3 "register_operand" "")))] "(TARGET_80387 && TARGET_CMOVE) diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 2089de768ce..196599bbe21 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -952,9 +952,7 @@ if (inmode == CCFPmode || inmode == CCFPUmode) { - enum rtx_code second_code, bypass_code; - ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code); - if (bypass_code != UNKNOWN || second_code != UNKNOWN) + if (!ix86_trivial_fp_comparison_operator (op, mode)) return 0; code = ix86_fp_compare_code_to_integer (code); } @@ -1014,11 +1012,8 @@ enum rtx_code code = GET_CODE (op); if (inmode == CCFPmode || inmode == CCFPUmode) - { - enum rtx_code second_code, bypass_code; - ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code); - return (bypass_code == UNKNOWN && second_code == UNKNOWN); - } + return ix86_trivial_fp_comparison_operator (op, mode); + switch (code) { case EQ: case NE: @@ -1059,9 +1054,7 @@ if (inmode == CCFPmode || inmode == CCFPUmode) { - enum rtx_code second_code, bypass_code; - ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code); - if (bypass_code != UNKNOWN || second_code != UNKNOWN) + if (!ix86_trivial_fp_comparison_operator (op, mode)) return 0; code = ix86_fp_compare_code_to_integer (code); } @@ -1073,6 +1066,19 @@ return code == LTU; }) +;; Return 1 if this comparison only requires testing one flag bit. +(define_predicate "ix86_trivial_fp_comparison_operator" + (match_code "gt,ge,unlt,unle,uneq,ltgt,ordered,unordered")) + +;; Return 1 if we know how to do this comparison. Others require +;; testing more than one flag bit, and we let the generic middle-end +;; code do that. +(define_predicate "ix86_fp_comparison_operator" + (if_then_else (match_test "ix86_fp_comparison_strategy (GET_CODE (op)) + == IX86_FPCMP_ARITH") + (match_operand 0 "comparison_operator") + (match_operand 0 "ix86_trivial_fp_comparison_operator"))) + ;; Nearly general operand, but accept any const_double, since we wish ;; to be able to drop them into memory rather than have them get pulled ;; into registers.