Commit 0948ccb2 by Paolo Bonzini Committed by Paolo Bonzini

i386.h (enum ix86_fpcmp_strategy): New.

2009-06-28  Paolo Bonzini  <bonzini@gnu.org>

        * config/i386/i386.h (enum ix86_fpcmp_strategy): New.
        * config/i386/i386.md (cbranchxf4, cstorexf4, cbranch<MODEF>4,
        cstore<MODEF>4, mov<X87MODEF>cc): 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<MODEF>_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.

From-SVN: r149035
parent accbd151
2009-06-28 Paolo Bonzini <bonzini@gnu.org> 2009-06-28 Paolo Bonzini <bonzini@gnu.org>
* config/i386/i386.h (enum ix86_fpcmp_strategy): New.
* config/i386/i386.md (cbranchxf4, cstorexf4, cbranch<MODEF>4,
cstore<MODEF>4, mov<X87MODEF>cc): 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<MODEF>_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 <bonzini@gnu.org>
* config/arm/arm.c (arm_final_prescan_ins): Eliminate code * config/arm/arm.c (arm_final_prescan_ins): Eliminate code
related to jump_clobbers. related to jump_clobbers.
* config/arm/arm.md (conds): Remove jump_clob case. * config/arm/arm.md (conds): Remove jump_clob case.
......
...@@ -95,6 +95,7 @@ extern void ix86_expand_convert_uns_sixf_sse (rtx, rtx); ...@@ -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_sidf_sse (rtx, rtx);
extern void ix86_expand_convert_uns_sisf_sse (rtx, rtx); extern void ix86_expand_convert_uns_sisf_sse (rtx, rtx);
extern void ix86_expand_convert_sign_didf_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, extern void ix86_expand_fp_absneg_operator (enum rtx_code, enum machine_mode,
rtx[]); rtx[]);
extern void ix86_expand_copysign (rtx []); extern void ix86_expand_copysign (rtx []);
...@@ -102,7 +103,7 @@ extern void ix86_split_copysign_const (rtx []); ...@@ -102,7 +103,7 @@ extern void ix86_split_copysign_const (rtx []);
extern void ix86_split_copysign_var (rtx []); extern void ix86_split_copysign_var (rtx []);
extern int ix86_unary_operator_ok (enum rtx_code, enum machine_mode, rtx[]); extern int ix86_unary_operator_ok (enum rtx_code, enum machine_mode, rtx[]);
extern int ix86_match_ccmode (rtx, enum machine_mode); 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 int ix86_use_fcomi_compare (enum rtx_code);
extern void ix86_expand_branch (enum rtx_code, rtx); extern void ix86_expand_branch (enum rtx_code, rtx);
extern void ix86_expand_setcc (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); ...@@ -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_memory_move_cost (enum machine_mode, enum reg_class, int);
extern int ix86_mode_needed (int, rtx); extern int ix86_mode_needed (int, rtx);
extern void emit_i387_cw_initialization (int); 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_order_regs_for_local_alloc (void);
extern void x86_function_profiler (FILE *, int); extern void x86_function_profiler (FILE *, int);
extern void x86_emit_floatuns (rtx [2]); extern void x86_emit_floatuns (rtx [2]);
......
...@@ -10838,9 +10838,6 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, int reverse, ...@@ -10838,9 +10838,6 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, int reverse,
if (mode == CCFPmode || mode == CCFPUmode) 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); code = ix86_fp_compare_code_to_integer (code);
mode = CCmode; mode = CCmode;
} }
...@@ -14465,84 +14462,41 @@ ix86_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2) ...@@ -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 /* Return a comparison we can do and that it is equivalent to
ix86_fp_comparison_codes (enum rtx_code code, enum rtx_code *bypass_code, swap_condition (code) apart possibly from orderedness.
enum rtx_code *first_code, But, never change orderedness if TARGET_IEEE_FP, returning
enum rtx_code *second_code) UNKNOWN in that case if necessary. */
{
*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 */
static enum rtx_code
ix86_fp_swap_condition (enum rtx_code code)
{
switch (code) switch (code)
{ {
case GT: /* GTU - CF=0 & ZF=0 */ case GT: /* GTU - CF=0 & ZF=0 */
case GE: /* GEU - CF=0 */ return TARGET_IEEE_FP ? UNKNOWN : UNLT;
case ORDERED: /* PF=0 */ case GE: /* GEU - CF=0 */
case UNORDERED: /* PF=1 */ return TARGET_IEEE_FP ? UNKNOWN : UNLE;
case UNEQ: /* EQ - ZF=1 */ case UNLT: /* LTU - CF=1 */
case UNLT: /* LTU - CF=1 */ return TARGET_IEEE_FP ? UNKNOWN : GT;
case UNLE: /* LEU - CF=1 | ZF=1 */ case UNLE: /* LEU - CF=1 | ZF=1 */
case LTGT: /* EQ - ZF=0 */ return TARGET_IEEE_FP ? UNKNOWN : GE;
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;
default: default:
gcc_unreachable (); return swap_condition (code);
}
if (!TARGET_IEEE_FP)
{
*second_code = UNKNOWN;
*bypass_code = UNKNOWN;
} }
} }
/* 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. 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 In future this should be tweaked to compute bytes for optimize_size and
take into account performance of various instructions on various CPUs. */ take into account performance of various instructions on various CPUs. */
static int static int
ix86_fp_comparison_arithmetics_cost (enum rtx_code code) ix86_fp_comparison_cost (enum rtx_code code)
{ {
if (!TARGET_IEEE_FP) int arith_cost;
return 4;
/* The cost of code output by ix86_expand_fp_compare. */ /* The cost of code using bit-twiddling on %ah. */
switch (code) switch (code)
{ {
case UNLE: case UNLE:
...@@ -14553,82 +14507,49 @@ ix86_fp_comparison_arithmetics_cost (enum rtx_code code) ...@@ -14553,82 +14507,49 @@ ix86_fp_comparison_arithmetics_cost (enum rtx_code code)
case UNORDERED: case UNORDERED:
case ORDERED: case ORDERED:
case UNEQ: case UNEQ:
return 4; arith_cost = 4;
break; break;
case LT: case LT:
case NE: case NE:
case EQ: case EQ:
case UNGE: case UNGE:
return 5; arith_cost = TARGET_IEEE_FP ? 5 : 4;
break; break;
case LE: case LE:
case UNGT: case UNGT:
return 6; arith_cost = TARGET_IEEE_FP ? 6 : 4;
break; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
}
/* Return cost of comparison done using fcomi operation. switch (ix86_fp_comparison_strategy (code))
See ix86_fp_comparison_arithmetics_cost for the metrics. */ {
static int case IX86_FPCMP_COMI:
ix86_fp_comparison_fcomi_cost (enum rtx_code code) return arith_cost > 4 ? 3 : 2;
{ case IX86_FPCMP_SAHF:
enum rtx_code bypass_code, first_code, second_code; return arith_cost > 4 ? 4 : 3;
/* Return arbitrarily high cost when instruction is not supported - this default:
prevents gcc from using it. */ return arith_cost;
if (!TARGET_CMOVE) }
return 1024;
ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
return (bypass_code != UNKNOWN || second_code != UNKNOWN) + 2;
} }
/* Return cost of comparison done using sahf operation. /* Return strategy to use for floating-point. We assume that fcomi is always
See ix86_fp_comparison_arithmetics_cost for the metrics. */ preferrable where available, since that is also true when looking at size
static int (2 bytes, vs. 3 for fnstsw+sahf and at least 5 for fnstsw+test). */
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;
}
/* Compute cost of the comparison done using any method. enum ix86_fpcmp_strategy
See ix86_fp_comparison_arithmetics_cost for the metrics. */ ix86_fp_comparison_strategy (enum rtx_code code ATTRIBUTE_UNUSED)
static int
ix86_fp_comparison_cost (enum rtx_code code)
{ {
int fcomi_cost, sahf_cost, arithmetics_cost = 1024; /* Do fcomi/sahf based test when profitable. */
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;
}
/* Return true if we should use an FCOMI instruction for this if (TARGET_CMOVE)
fp comparison. */ return IX86_FPCMP_COMI;
int if (TARGET_SAHF && (TARGET_USE_SAHF || optimize_insn_for_size_p ()))
ix86_use_fcomi_compare (enum rtx_code code ATTRIBUTE_UNUSED) return IX86_FPCMP_SAHF;
{
enum rtx_code swapped_code = swap_condition (code);
return ((ix86_fp_comparison_cost (code) return IX86_FPCMP_ARITH;
== ix86_fp_comparison_fcomi_cost (code))
|| (ix86_fp_comparison_cost (swapped_code)
== ix86_fp_comparison_fcomi_cost (swapped_code)));
} }
/* Swap, force into registers, or otherwise massage the two operands /* 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) ...@@ -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 (op0) == 1
|| standard_80387_constant_p (op1) == 1) || standard_80387_constant_p (op1) == 1)
&& GET_CODE (op1) != FLOAT) && GET_CODE (op1) != FLOAT)
|| ix86_use_fcomi_compare (code))) || ix86_fp_comparison_strategy (code) == IX86_FPCMP_COMI))
{ {
op0 = force_reg (op_mode, op0); op0 = force_reg (op_mode, op0);
op1 = force_reg (op_mode, op1); op1 = force_reg (op_mode, op1);
...@@ -14671,9 +14592,13 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1) ...@@ -14671,9 +14592,13 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
&& ! (standard_80387_constant_p (op1) == 0 && ! (standard_80387_constant_p (op1) == 0
|| MEM_P (op1)))) || MEM_P (op1))))
{ {
rtx tmp; enum rtx_code new_code = ix86_fp_swap_condition (code);
tmp = op0, op0 = op1, op1 = tmp; if (new_code != UNKNOWN)
code = swap_condition (code); {
rtx tmp;
tmp = op0, op0 = op1, op1 = tmp;
code = new_code;
}
} }
if (!REG_P (op0)) if (!REG_P (op0))
...@@ -14748,59 +14673,38 @@ ix86_fp_compare_code_to_integer (enum rtx_code code) ...@@ -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. */ /* Generate insn patterns to do a floating point compare of OPERANDS. */
static rtx static rtx
ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch, ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
rtx *second_test, rtx *bypass_test)
{ {
enum machine_mode fpcmp_mode, intcmp_mode; enum machine_mode fpcmp_mode, intcmp_mode;
rtx tmp, tmp2; 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); fpcmp_mode = ix86_fp_compare_mode (code);
code = ix86_prepare_fp_compare_args (code, &op0, &op1); 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. */ /* Do fcomi/sahf based test when profitable. */
if (ix86_fp_comparison_arithmetics_cost (code) > cost switch (ix86_fp_comparison_strategy (code))
&& (bypass_code == UNKNOWN || bypass_test)
&& (second_code == UNKNOWN || second_test))
{ {
case IX86_FPCMP_COMI:
intcmp_mode = fpcmp_mode;
tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
tmp = gen_rtx_SET (VOIDmode, gen_rtx_REG (fpcmp_mode, FLAGS_REG), tmp = gen_rtx_SET (VOIDmode, gen_rtx_REG (fpcmp_mode, FLAGS_REG),
tmp); tmp);
if (TARGET_CMOVE) emit_insn (tmp);
emit_insn (tmp); break;
else
{
gcc_assert (TARGET_SAHF);
if (!scratch) case IX86_FPCMP_SAHF:
scratch = gen_reg_rtx (HImode); intcmp_mode = fpcmp_mode;
tmp2 = gen_rtx_CLOBBER (VOIDmode, scratch); 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. */ case IX86_FPCMP_ARITH:
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
{
/* Sadness wrt reg-stack pops killing fpsr -- gotta get fnstsw first. */ /* Sadness wrt reg-stack pops killing fpsr -- gotta get fnstsw first. */
tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW); 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, ...@@ -14922,6 +14826,10 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch,
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
break;
default:
gcc_unreachable();
} }
/* Return the test that should be put into the flags user, i.e. /* 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, ...@@ -14932,25 +14840,19 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch,
} }
rtx 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; rtx op0, op1, ret;
op0 = ix86_compare_op0; op0 = ix86_compare_op0;
op1 = ix86_compare_op1; 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) if (GET_MODE_CLASS (GET_MODE (ix86_compare_op0)) == MODE_CC)
ret = gen_rtx_fmt_ee (code, VOIDmode, ix86_compare_op0, ix86_compare_op1); ret = gen_rtx_fmt_ee (code, VOIDmode, ix86_compare_op0, ix86_compare_op1);
else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0))) else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0)))
{ {
gcc_assert (!DECIMAL_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, ret = ix86_expand_fp_compare (code, op0, op1, NULL_RTX);
second_test, bypass_test);
} }
else else
ret = ix86_expand_int_compare (code, op0, op1); 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) ...@@ -14958,17 +14860,6 @@ ix86_expand_compare (enum rtx_code code, rtx *second_test, rtx *bypass_test)
return ret; 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 void
ix86_expand_branch (enum rtx_code code, rtx label) ix86_expand_branch (enum rtx_code code, rtx label)
{ {
...@@ -14976,64 +14867,20 @@ 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)) switch (GET_MODE (ix86_compare_op0))
{ {
case SFmode:
case DFmode:
case XFmode:
case QImode: case QImode:
case HImode: case HImode:
case SImode: case SImode:
simple: simple:
tmp = ix86_expand_compare (code, NULL, NULL); tmp = ix86_expand_compare (code);
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
gen_rtx_LABEL_REF (VOIDmode, label), gen_rtx_LABEL_REF (VOIDmode, label),
pc_rtx); pc_rtx);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
return; 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: case DImode:
if (TARGET_64BIT) if (TARGET_64BIT)
goto simple; goto simple;
...@@ -15187,10 +15034,7 @@ void ...@@ -15187,10 +15034,7 @@ void
ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2, ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2,
rtx target1, rtx target2, rtx tmp, rtx pushed) rtx target1, rtx target2, rtx tmp, rtx pushed)
{ {
rtx second, bypass;
rtx label = NULL_RTX;
rtx condition; rtx condition;
int bypass_probability = -1, second_probability = -1, probability = -1;
rtx i; rtx i;
if (target2 != pc_rtx) if (target2 != pc_rtx)
...@@ -15202,103 +15046,30 @@ ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2, ...@@ -15202,103 +15046,30 @@ ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2,
} }
condition = ix86_expand_fp_compare (code, op1, op2, condition = ix86_expand_fp_compare (code, op1, op2,
tmp, &second, &bypass); tmp);
/* Remove pushed operand from stack. */ /* Remove pushed operand from stack. */
if (pushed) if (pushed)
ix86_free_from_memory (GET_MODE (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 i = emit_jump_insn (gen_rtx_SET
(VOIDmode, pc_rtx, (VOIDmode, pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode, gen_rtx_IF_THEN_ELSE (VOIDmode,
condition, target1, target2))); condition, target1, target2)));
if (probability >= 0) if (split_branch_probability >= 0)
add_reg_note (i, REG_BR_PROB, GEN_INT (probability)); add_reg_note (i, REG_BR_PROB, GEN_INT (split_branch_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);
} }
void void
ix86_expand_setcc (enum rtx_code code, rtx dest) ix86_expand_setcc (enum rtx_code code, rtx dest)
{ {
rtx ret, tmp, tmpreg, equiv; rtx ret;
rtx second_test, bypass_test;
gcc_assert (GET_MODE (dest) == QImode); gcc_assert (GET_MODE (dest) == QImode);
ret = ix86_expand_compare (code, &second_test, &bypass_test); ret = ix86_expand_compare (code);
PUT_MODE (ret, QImode); PUT_MODE (ret, QImode);
emit_insn (gen_rtx_SET (VOIDmode, dest, ret));
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);
}
} }
/* Expand comparison setting or clearing carry flag. Return true when /* 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) ...@@ -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)) if (SCALAR_FLOAT_MODE_P (mode))
{ {
rtx second_test = NULL, bypass_test = NULL;
rtx compare_op, compare_seq; rtx compare_op, compare_seq;
gcc_assert (!DECIMAL_FLOAT_MODE_P (mode)); 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) ...@@ -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 we decide to expand comparison using arithmetic that is not
too common scenario. */ too common scenario. */
start_sequence (); start_sequence ();
compare_op = ix86_expand_fp_compare (code, op0, op1, NULL_RTX, compare_op = ix86_expand_fp_compare (code, op0, op1, NULL_RTX);
&second_test, &bypass_test);
compare_seq = get_insns (); compare_seq = get_insns ();
end_sequence (); end_sequence ();
if (second_test || bypass_test)
return false;
if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
|| GET_MODE (XEXP (compare_op, 0)) == CCFPUmode) || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op)); 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) ...@@ -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_op0 = op0;
ix86_compare_op1 = op1; 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); gcc_assert (GET_CODE (*pop) == LTU || GET_CODE (*pop) == GEU);
return true; return true;
} }
...@@ -15441,14 +15207,13 @@ ix86_expand_int_movcc (rtx operands[]) ...@@ -15441,14 +15207,13 @@ ix86_expand_int_movcc (rtx operands[])
{ {
enum rtx_code code = GET_CODE (operands[1]), compare_code; enum rtx_code code = GET_CODE (operands[1]), compare_code;
rtx compare_seq, compare_op; rtx compare_seq, compare_op;
rtx second_test, bypass_test;
enum machine_mode mode = GET_MODE (operands[0]); enum machine_mode mode = GET_MODE (operands[0]);
bool sign_bit_compare_p = false;; bool sign_bit_compare_p = false;;
start_sequence (); start_sequence ();
ix86_compare_op0 = XEXP (operands[1], 0); ix86_compare_op0 = XEXP (operands[1], 0);
ix86_compare_op1 = XEXP (operands[1], 1); 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 (); compare_seq = get_insns ();
end_sequence (); end_sequence ();
...@@ -15920,19 +15685,6 @@ ix86_expand_int_movcc (rtx operands[]) ...@@ -15920,19 +15685,6 @@ ix86_expand_int_movcc (rtx operands[])
if (! nonimmediate_operand (operands[3], mode)) if (! nonimmediate_operand (operands[3], mode))
operands[3] = force_reg (mode, operands[3]); 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) if (! register_operand (operands[2], VOIDmode)
&& (mode == QImode && (mode == QImode
|| ! register_operand (operands[3], VOIDmode))) || ! register_operand (operands[3], VOIDmode)))
...@@ -15947,18 +15699,6 @@ ix86_expand_int_movcc (rtx operands[]) ...@@ -15947,18 +15699,6 @@ ix86_expand_int_movcc (rtx operands[])
gen_rtx_IF_THEN_ELSE (mode, gen_rtx_IF_THEN_ELSE (mode,
compare_op, operands[2], compare_op, operands[2],
operands[3]))); 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 */ return 1; /* DONE */
} }
...@@ -16163,7 +15903,7 @@ ix86_expand_fp_movcc (rtx operands[]) ...@@ -16163,7 +15903,7 @@ ix86_expand_fp_movcc (rtx operands[])
{ {
enum machine_mode mode = GET_MODE (operands[0]); enum machine_mode mode = GET_MODE (operands[0]);
enum rtx_code code = GET_CODE (operands[1]); 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_op0 = XEXP (operands[1], 0);
ix86_compare_op1 = XEXP (operands[1], 1); ix86_compare_op1 = XEXP (operands[1], 1);
...@@ -16200,45 +15940,20 @@ ix86_expand_fp_movcc (rtx operands[]) ...@@ -16200,45 +15940,20 @@ ix86_expand_fp_movcc (rtx operands[])
/* The floating point conditional move instructions don't directly /* The floating point conditional move instructions don't directly
support conditions resulting from a signed integer comparison. */ support conditions resulting from a signed integer comparison. */
compare_op = ix86_expand_compare (code, &second_test, &bypass_test); compare_op = ix86_expand_compare (code);
/* The floating point conditional move instructions don't directly
support signed integer comparisons. */
if (!fcmov_comparison_operator (compare_op, VOIDmode)) if (!fcmov_comparison_operator (compare_op, VOIDmode))
{ {
gcc_assert (!second_test && !bypass_test);
tmp = gen_reg_rtx (QImode); tmp = gen_reg_rtx (QImode);
ix86_expand_setcc (code, tmp); ix86_expand_setcc (code, tmp);
code = NE; code = NE;
ix86_compare_op0 = tmp; ix86_compare_op0 = tmp;
ix86_compare_op1 = const0_rtx; ix86_compare_op1 = const0_rtx;
compare_op = ix86_expand_compare (code, &second_test, &bypass_test); compare_op = ix86_expand_compare (code);
}
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;
} }
emit_insn (gen_rtx_SET (VOIDmode, operands[0], emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (mode, compare_op, gen_rtx_IF_THEN_ELSE (mode, compare_op,
operands[2], operands[3]))); 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; return 1;
} }
......
...@@ -2308,6 +2308,12 @@ extern enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER]; ...@@ -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_op0; /* operand 0 for comparisons */
extern rtx ix86_compare_op1; /* operand 1 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 /* 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 word. We can't emit proper mode switching code before reload, as spills
......
...@@ -1222,7 +1222,7 @@ ...@@ -1222,7 +1222,7 @@
(compare:CC (match_operand:XF 1 "nonmemory_operand" "") (compare:CC (match_operand:XF 1 "nonmemory_operand" "")
(match_operand:XF 2 "nonmemory_operand" ""))) (match_operand:XF 2 "nonmemory_operand" "")))
(set (pc) (if_then_else (set (pc) (if_then_else
(match_operator 0 "comparison_operator" (match_operator 0 "ix86_fp_comparison_operator"
[(reg:CC FLAGS_REG) [(reg:CC FLAGS_REG)
(const_int 0)]) (const_int 0)])
(label_ref (match_operand 3 "" "")) (label_ref (match_operand 3 "" ""))
...@@ -1240,7 +1240,7 @@ ...@@ -1240,7 +1240,7 @@
(compare:CC (match_operand:XF 2 "nonmemory_operand" "") (compare:CC (match_operand:XF 2 "nonmemory_operand" "")
(match_operand:XF 3 "nonmemory_operand" ""))) (match_operand:XF 3 "nonmemory_operand" "")))
(set (match_operand:QI 0 "register_operand" "") (set (match_operand:QI 0 "register_operand" "")
(match_operator 1 "comparison_operator" (match_operator 1 "ix86_fp_comparison_operator"
[(reg:CC FLAGS_REG) [(reg:CC FLAGS_REG)
(const_int 0)]))] (const_int 0)]))]
"TARGET_80387" "TARGET_80387"
...@@ -1256,7 +1256,7 @@ ...@@ -1256,7 +1256,7 @@
(compare:CC (match_operand:MODEF 1 "cmp_fp_expander_operand" "") (compare:CC (match_operand:MODEF 1 "cmp_fp_expander_operand" "")
(match_operand:MODEF 2 "cmp_fp_expander_operand" ""))) (match_operand:MODEF 2 "cmp_fp_expander_operand" "")))
(set (pc) (if_then_else (set (pc) (if_then_else
(match_operator 0 "comparison_operator" (match_operator 0 "ix86_fp_comparison_operator"
[(reg:CC FLAGS_REG) [(reg:CC FLAGS_REG)
(const_int 0)]) (const_int 0)])
(label_ref (match_operand 3 "" "")) (label_ref (match_operand 3 "" ""))
...@@ -1274,7 +1274,7 @@ ...@@ -1274,7 +1274,7 @@
(compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand" "") (compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand" "")
(match_operand:MODEF 3 "cmp_fp_expander_operand" ""))) (match_operand:MODEF 3 "cmp_fp_expander_operand" "")))
(set (match_operand:QI 0 "register_operand" "") (set (match_operand:QI 0 "register_operand" "")
(match_operator 1 "comparison_operator" (match_operator 1 "ix86_fp_comparison_operator"
[(reg:CC FLAGS_REG) [(reg:CC FLAGS_REG)
(const_int 0)]))] (const_int 0)]))]
"TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
...@@ -15131,103 +15131,12 @@ ...@@ -15131,103 +15131,12 @@
(pc)))] (pc)))]
"PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));") "PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));")
;; Define combination compare-and-branch fp compare instructions to use ;; Define combination compare-and-branch fp compare instructions to help
;; during early optimization. Splitting the operation apart early makes ;; combine.
;; 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_insn "*fp_jcc_3_387" (define_insn "*fp_jcc_3_387"
[(set (pc) [(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 1 "register_operand" "f")
(match_operand 2 "nonimmediate_operand" "fm")]) (match_operand 2 "nonimmediate_operand" "fm")])
(label_ref (match_operand 3 "" "")) (label_ref (match_operand 3 "" ""))
...@@ -15238,15 +15147,14 @@ ...@@ -15238,15 +15147,14 @@
"TARGET_80387 "TARGET_80387
&& (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode) && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && GET_MODE (operands[1]) == GET_MODE (operands[2])
&& !ix86_use_fcomi_compare (GET_CODE (operands[0]))
&& SELECT_CC_MODE (GET_CODE (operands[0]), && SELECT_CC_MODE (GET_CODE (operands[0]),
operands[1], operands[2]) == CCFPmode operands[1], operands[2]) == CCFPmode
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && !TARGET_CMOVE"
"#") "#")
(define_insn "*fp_jcc_4_387" (define_insn "*fp_jcc_4_387"
[(set (pc) [(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 1 "register_operand" "f")
(match_operand 2 "nonimmediate_operand" "fm")]) (match_operand 2 "nonimmediate_operand" "fm")])
(pc) (pc)
...@@ -15257,15 +15165,14 @@ ...@@ -15257,15 +15165,14 @@
"TARGET_80387 "TARGET_80387
&& (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode) && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && GET_MODE (operands[1]) == GET_MODE (operands[2])
&& !ix86_use_fcomi_compare (GET_CODE (operands[0]))
&& SELECT_CC_MODE (GET_CODE (operands[0]), && SELECT_CC_MODE (GET_CODE (operands[0]),
operands[1], operands[2]) == CCFPmode operands[1], operands[2]) == CCFPmode
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && !TARGET_CMOVE"
"#") "#")
(define_insn "*fp_jcc_5_387" (define_insn "*fp_jcc_5_387"
[(set (pc) [(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 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")]) (match_operand 2 "register_operand" "f")])
(label_ref (match_operand 3 "" "")) (label_ref (match_operand 3 "" ""))
...@@ -15275,12 +15182,12 @@ ...@@ -15275,12 +15182,12 @@
(clobber (match_scratch:HI 4 "=a"))] (clobber (match_scratch:HI 4 "=a"))]
"X87_FLOAT_MODE_P (GET_MODE (operands[1])) "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && 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" (define_insn "*fp_jcc_6_387"
[(set (pc) [(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 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")]) (match_operand 2 "register_operand" "f")])
(pc) (pc)
...@@ -15290,12 +15197,12 @@ ...@@ -15290,12 +15197,12 @@
(clobber (match_scratch:HI 4 "=a"))] (clobber (match_scratch:HI 4 "=a"))]
"X87_FLOAT_MODE_P (GET_MODE (operands[1])) "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && 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" (define_insn "*fp_jcc_7_387"
[(set (pc) [(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 1 "register_operand" "f")
(match_operand 2 "const0_operand" "")]) (match_operand 2 "const0_operand" "")])
(label_ref (match_operand 3 "" "")) (label_ref (match_operand 3 "" ""))
...@@ -15305,10 +15212,9 @@ ...@@ -15305,10 +15212,9 @@
(clobber (match_scratch:HI 4 "=a"))] (clobber (match_scratch:HI 4 "=a"))]
"X87_FLOAT_MODE_P (GET_MODE (operands[1])) "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && GET_MODE (operands[1]) == GET_MODE (operands[2])
&& !ix86_use_fcomi_compare (GET_CODE (operands[0]))
&& SELECT_CC_MODE (GET_CODE (operands[0]), && SELECT_CC_MODE (GET_CODE (operands[0]),
operands[1], operands[2]) == CCFPmode 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 ;; The order of operands in *fp_jcc_8_387 is forced by combine in
...@@ -15318,7 +15224,7 @@ ...@@ -15318,7 +15224,7 @@
(define_insn "*fp_jcc_8<mode>_387" (define_insn "*fp_jcc_8<mode>_387"
[(set (pc) [(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_operator 1 "float_operator"
[(match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r")]) [(match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r")])
(match_operand 3 "register_operand" "f,f")]) (match_operand 3 "register_operand" "f,f")])
...@@ -15330,14 +15236,13 @@ ...@@ -15330,14 +15236,13 @@
"X87_FLOAT_MODE_P (GET_MODE (operands[3])) "X87_FLOAT_MODE_P (GET_MODE (operands[3]))
&& (TARGET_USE_<MODE>MODE_FIOP || optimize_function_for_size_p (cfun)) && (TARGET_USE_<MODE>MODE_FIOP || optimize_function_for_size_p (cfun))
&& GET_MODE (operands[1]) == GET_MODE (operands[3]) && 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_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode
&& ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))" && !TARGET_CMOVE"
"#") "#")
(define_split (define_split
[(set (pc) [(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 1 "register_operand" "")
(match_operand 2 "nonimmediate_operand" "")]) (match_operand 2 "nonimmediate_operand" "")])
(match_operand 3 "" "") (match_operand 3 "" "")
...@@ -15354,7 +15259,7 @@ ...@@ -15354,7 +15259,7 @@
(define_split (define_split
[(set (pc) [(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 1 "register_operand" "")
(match_operand 2 "general_operand" "")]) (match_operand 2 "general_operand" "")])
(match_operand 3 "" "") (match_operand 3 "" "")
...@@ -15372,7 +15277,7 @@ ...@@ -15372,7 +15277,7 @@
(define_split (define_split
[(set (pc) [(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_operator 1 "float_operator"
[(match_operand:X87MODEI12 2 "memory_operand" "")]) [(match_operand:X87MODEI12 2 "memory_operand" "")])
(match_operand 3 "register_operand" "")]) (match_operand 3 "register_operand" "")])
...@@ -15394,7 +15299,7 @@ ...@@ -15394,7 +15299,7 @@
;; %%% Kill this when reload knows how to do it. ;; %%% Kill this when reload knows how to do it.
(define_split (define_split
[(set (pc) [(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_operator 1 "float_operator"
[(match_operand:X87MODEI12 2 "register_operand" "")]) [(match_operand:X87MODEI12 2 "register_operand" "")])
(match_operand 3 "register_operand" "")]) (match_operand 3 "register_operand" "")])
...@@ -20657,7 +20562,7 @@ ...@@ -20657,7 +20562,7 @@
(define_expand "mov<mode>cc" (define_expand "mov<mode>cc"
[(set (match_operand:X87MODEF 0 "register_operand" "") [(set (match_operand:X87MODEF 0 "register_operand" "")
(if_then_else:X87MODEF (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 2 "register_operand" "")
(match_operand:X87MODEF 3 "register_operand" "")))] (match_operand:X87MODEF 3 "register_operand" "")))]
"(TARGET_80387 && TARGET_CMOVE) "(TARGET_80387 && TARGET_CMOVE)
......
...@@ -952,9 +952,7 @@ ...@@ -952,9 +952,7 @@
if (inmode == CCFPmode || inmode == CCFPUmode) if (inmode == CCFPmode || inmode == CCFPUmode)
{ {
enum rtx_code second_code, bypass_code; if (!ix86_trivial_fp_comparison_operator (op, mode))
ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
if (bypass_code != UNKNOWN || second_code != UNKNOWN)
return 0; return 0;
code = ix86_fp_compare_code_to_integer (code); code = ix86_fp_compare_code_to_integer (code);
} }
...@@ -1014,11 +1012,8 @@ ...@@ -1014,11 +1012,8 @@
enum rtx_code code = GET_CODE (op); enum rtx_code code = GET_CODE (op);
if (inmode == CCFPmode || inmode == CCFPUmode) if (inmode == CCFPmode || inmode == CCFPUmode)
{ return ix86_trivial_fp_comparison_operator (op, mode);
enum rtx_code second_code, bypass_code;
ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
return (bypass_code == UNKNOWN && second_code == UNKNOWN);
}
switch (code) switch (code)
{ {
case EQ: case NE: case EQ: case NE:
...@@ -1059,9 +1054,7 @@ ...@@ -1059,9 +1054,7 @@
if (inmode == CCFPmode || inmode == CCFPUmode) if (inmode == CCFPmode || inmode == CCFPUmode)
{ {
enum rtx_code second_code, bypass_code; if (!ix86_trivial_fp_comparison_operator (op, mode))
ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
if (bypass_code != UNKNOWN || second_code != UNKNOWN)
return 0; return 0;
code = ix86_fp_compare_code_to_integer (code); code = ix86_fp_compare_code_to_integer (code);
} }
...@@ -1073,6 +1066,19 @@ ...@@ -1073,6 +1066,19 @@
return code == LTU; 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 ;; 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 ;; to be able to drop them into memory rather than have them get pulled
;; into registers. ;; into registers.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment