aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2009-06-28 17:06:11 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2009-06-28 17:06:11 +0000
commit0948ccb243a5b2244bef375addc6f1a4b3a2f526 (patch)
tree6c2efbe4264d6844ad652c064def3e3644438024 /gcc
parentaccbd1518f6afdadb59649585197f8a7928555b5 (diff)
downloadgcc-0948ccb243a5b2244bef375addc6f1a4b3a2f526.zip
gcc-0948ccb243a5b2244bef375addc6f1a4b3a2f526.tar.gz
gcc-0948ccb243a5b2244bef375addc6f1a4b3a2f526.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog39
-rw-r--r--gcc/config/i386/i386-protos.h4
-rw-r--r--gcc/config/i386/i386.c469
-rw-r--r--gcc/config/i386/i386.h6
-rw-r--r--gcc/config/i386/i386.md141
-rw-r--r--gcc/config/i386/predicates.md28
6 files changed, 179 insertions, 508 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index db35ccf..436ea0d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,44 @@
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
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 8ae5bd6..663b4bf 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 06ae734..81f3b9e 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 7592f6b..d762c29 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 a71ca43..33ff7a5 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>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<mode>_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>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 "mov<mode>cc"
[(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 2089de7..196599b 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.