Commit 45475a3f by Paolo Bonzini Committed by Paolo Bonzini

dojump.c (do_compare_rtx_and_jump): Try swapping the condition for floating point modes.

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

        * dojump.c (do_compare_rtx_and_jump): Try swapping the
        condition for floating point modes.
        * expmed.c (emit_store_flag_1): Move here a bigger part
        of emit_store_flag.
        (emit_store_flag): Try swapping the condition for floating point
        modes.
        * optabs.c (emit_cmp_and_jump_insns): Cope with constant op0 better.

From-SVN: r149033
parent 495499da
2009-06-28 Paolo Bonzini <bonzini@gnu.org> 2009-06-28 Paolo Bonzini <bonzini@gnu.org>
* dojump.c (do_compare_rtx_and_jump): Try swapping the
condition for floating point modes.
* expmed.c (emit_store_flag_1): Move here a bigger part
of emit_store_flag.
(emit_store_flag): Try swapping the condition for floating point
modes.
* optabs.c (emit_cmp_and_jump_insns): Cope with constant op0 better.
2009-06-28 Paolo Bonzini <bonzini@gnu.org>
* expr.c (expand_expr_real_1): Just use do_store_flag. * expr.c (expand_expr_real_1): Just use do_store_flag.
(do_store_flag): Drop support for TRUTH_NOT_EXPR. Use (do_store_flag): Drop support for TRUTH_NOT_EXPR. Use
emit_store_flag_force. emit_store_flag_force.
......
...@@ -920,6 +920,17 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, ...@@ -920,6 +920,17 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
{ {
if (GET_MODE_CLASS (mode) == MODE_FLOAT if (GET_MODE_CLASS (mode) == MODE_FLOAT
&& ! can_compare_p (code, mode, ccp_jump) && ! can_compare_p (code, mode, ccp_jump)
&& can_compare_p (swap_condition (code), mode, ccp_jump))
{
rtx tmp;
code = swap_condition (code);
tmp = op0;
op0 = op1;
op1 = tmp;
}
else if (GET_MODE_CLASS (mode) == MODE_FLOAT
&& ! can_compare_p (code, mode, ccp_jump)
/* Never split ORDERED and UNORDERED. These must be implemented. */ /* Never split ORDERED and UNORDERED. These must be implemented. */
&& (code != ORDERED && code != UNORDERED) && (code != ORDERED && code != UNORDERED)
......
...@@ -5115,11 +5115,40 @@ expand_and (enum machine_mode mode, rtx op0, rtx op1, rtx target) ...@@ -5115,11 +5115,40 @@ expand_and (enum machine_mode mode, rtx op0, rtx op1, rtx target)
/* Helper function for emit_store_flag. */ /* Helper function for emit_store_flag. */
static rtx static rtx
emit_store_flag_1 (rtx target, rtx subtarget, enum machine_mode mode, emit_store_flag_1 (rtx target, enum insn_code icode, enum rtx_code code,
int normalizep) enum machine_mode mode, enum machine_mode compare_mode,
int unsignedp, rtx x, rtx y, int normalizep)
{ {
rtx op0; rtx op0, last, comparison, subtarget, pattern;
enum machine_mode target_mode; enum machine_mode target_mode;
enum machine_mode result_mode = insn_data[(int) icode].operand[0].mode;
last = get_last_insn ();
x = prepare_operand (icode, x, 2, mode, compare_mode, unsignedp);
y = prepare_operand (icode, y, 3, mode, compare_mode, unsignedp);
comparison = gen_rtx_fmt_ee (code, result_mode, x, y);
if (!x || !y
|| !insn_data[icode].operand[2].predicate
(x, insn_data[icode].operand[2].mode)
|| !insn_data[icode].operand[3].predicate
(y, insn_data[icode].operand[3].mode)
|| !insn_data[icode].operand[1].predicate (comparison, VOIDmode))
{
delete_insns_since (last);
return NULL_RTX;
}
if (!target
|| optimize
|| !(insn_data[(int) icode].operand[0].predicate (target, result_mode)))
subtarget = gen_reg_rtx (result_mode);
else
subtarget = target;
pattern = GEN_FCN (icode) (subtarget, comparison, x, y);
if (!pattern)
return NULL_RTX;
emit_insn (pattern);
if (!target) if (!target)
target = gen_reg_rtx (GET_MODE (subtarget)); target = gen_reg_rtx (GET_MODE (subtarget));
...@@ -5133,15 +5162,15 @@ emit_store_flag_1 (rtx target, rtx subtarget, enum machine_mode mode, ...@@ -5133,15 +5162,15 @@ emit_store_flag_1 (rtx target, rtx subtarget, enum machine_mode mode,
If STORE_FLAG_VALUE does not have the sign bit set when If STORE_FLAG_VALUE does not have the sign bit set when
interpreted in MODE, we can do this conversion as unsigned, which interpreted in MODE, we can do this conversion as unsigned, which
is usually more efficient. */ is usually more efficient. */
if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (mode)) if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (result_mode))
{ {
convert_move (target, subtarget, convert_move (target, subtarget,
(GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) (GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT)
&& 0 == (STORE_FLAG_VALUE && 0 == (STORE_FLAG_VALUE
& ((HOST_WIDE_INT) 1 & ((HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (mode) -1)))); << (GET_MODE_BITSIZE (result_mode) -1))));
op0 = target; op0 = target;
mode = target_mode; result_mode = target_mode;
} }
else else
op0 = subtarget; op0 = subtarget;
...@@ -5158,28 +5187,28 @@ emit_store_flag_1 (rtx target, rtx subtarget, enum machine_mode mode, ...@@ -5158,28 +5187,28 @@ emit_store_flag_1 (rtx target, rtx subtarget, enum machine_mode mode,
/* STORE_FLAG_VALUE might be the most negative number, so write /* STORE_FLAG_VALUE might be the most negative number, so write
the comparison this way to avoid a compiler-time warning. */ the comparison this way to avoid a compiler-time warning. */
else if (- normalizep == STORE_FLAG_VALUE) else if (- normalizep == STORE_FLAG_VALUE)
op0 = expand_unop (mode, neg_optab, op0, subtarget, 0); op0 = expand_unop (result_mode, neg_optab, op0, subtarget, 0);
/* We don't want to use STORE_FLAG_VALUE < 0 below since this makes /* We don't want to use STORE_FLAG_VALUE < 0 below since this makes
it hard to use a value of just the sign bit due to ANSI integer it hard to use a value of just the sign bit due to ANSI integer
constant typing rules. */ constant typing rules. */
else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT else if (GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT
&& (STORE_FLAG_VALUE && (STORE_FLAG_VALUE
& ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))) & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (result_mode) - 1))))
op0 = expand_shift (RSHIFT_EXPR, mode, op0, op0 = expand_shift (RSHIFT_EXPR, result_mode, op0,
size_int (GET_MODE_BITSIZE (mode) - 1), subtarget, size_int (GET_MODE_BITSIZE (result_mode) - 1), subtarget,
normalizep == 1); normalizep == 1);
else else
{ {
gcc_assert (STORE_FLAG_VALUE & 1); gcc_assert (STORE_FLAG_VALUE & 1);
op0 = expand_and (mode, op0, const1_rtx, subtarget); op0 = expand_and (result_mode, op0, const1_rtx, subtarget);
if (normalizep == -1) if (normalizep == -1)
op0 = expand_unop (mode, neg_optab, op0, op0, 0); op0 = expand_unop (result_mode, neg_optab, op0, op0, 0);
} }
/* If we were converting to a smaller mode, do the conversion now. */ /* If we were converting to a smaller mode, do the conversion now. */
if (target_mode != mode) if (target_mode != result_mode)
{ {
convert_move (target, op0, 0); convert_move (target, op0, 0);
return target; return target;
...@@ -5213,12 +5242,13 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1, ...@@ -5213,12 +5242,13 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
enum machine_mode target_mode = target ? GET_MODE (target) : VOIDmode; enum machine_mode target_mode = target ? GET_MODE (target) : VOIDmode;
enum mode_class mclass; enum mode_class mclass;
enum rtx_code rcode; enum rtx_code rcode;
enum rtx_code scode;
rtx tem, trueval; rtx tem, trueval;
rtx last; rtx last;
rtx pattern, comparison;
if (unsignedp) if (unsignedp)
code = unsigned_condition (code); code = unsigned_condition (code);
scode = swap_condition (code);
/* If one operand is constant, make it the second one. Only do this /* If one operand is constant, make it the second one. Only do this
if the other operand is not constant as well. */ if the other operand is not constant as well. */
...@@ -5359,44 +5389,19 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1, ...@@ -5359,44 +5389,19 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
icode = optab_handler (cstore_optab, optab_mode)->insn_code; icode = optab_handler (cstore_optab, optab_mode)->insn_code;
if (icode != CODE_FOR_nothing) if (icode != CODE_FOR_nothing)
{ {
rtx x, y;
enum machine_mode result_mode
= insn_data[(int) icode].operand[0].mode;
do_pending_stack_adjust (); do_pending_stack_adjust ();
last = get_last_insn (); tem = emit_store_flag_1 (target, icode, code, mode, compare_mode,
unsignedp, op0, op1, normalizep);
x = prepare_operand (icode, op0, 2, mode, compare_mode, unsignedp); if (tem)
y = prepare_operand (icode, op1, 3, mode, compare_mode, unsignedp); return tem;
comparison = gen_rtx_fmt_ee (code, result_mode, x, y);
if (!x || !y
|| !insn_data[icode].operand[2].predicate
(x, insn_data[icode].operand[2].mode)
|| !insn_data[icode].operand[3].predicate
(y, insn_data[icode].operand[3].mode)
|| !insn_data[icode].operand[1].predicate (comparison, VOIDmode))
{
delete_insns_since (last);
continue;
}
if (!target
|| optimize
|| !(insn_data[(int) icode].operand[0].predicate (target, result_mode)))
subtarget = gen_reg_rtx (result_mode);
else
subtarget = target;
pattern = GEN_FCN (icode) (subtarget, comparison, x, y);
if (pattern) if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{ {
emit_insn (pattern); tem = emit_store_flag_1 (target, icode, scode, mode, compare_mode,
return emit_store_flag_1 (target, subtarget, result_mode, unsignedp, op1, op0, normalizep);
normalizep); if (tem)
return tem;
} }
delete_insns_since (last);
break; break;
} }
} }
......
...@@ -4280,18 +4280,18 @@ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size, ...@@ -4280,18 +4280,18 @@ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
rtx test; rtx test;
/* Swap operands and condition to ensure canonical RTL. */ /* Swap operands and condition to ensure canonical RTL. */
if (swap_commutative_operands_p (x, y)) if (swap_commutative_operands_p (x, y)
&& can_compare_p (swap_condition (comparison), mode, ccp_jump))
{ {
op0 = y, op1 = x; op0 = y, op1 = x;
comparison = swap_condition (comparison); comparison = swap_condition (comparison);
} }
#ifdef HAVE_cc0 /* If OP0 is still a constant, then both X and Y must be constants
/* If OP0 is still a constant, then both X and Y must be constants. or the opposite comparison is not supported. Force X into a register
Force X into a register to create canonical RTL. */ to create canonical RTL. */
if (CONSTANT_P (op0)) if (CONSTANT_P (op0))
op0 = force_reg (mode, op0); op0 = force_reg (mode, op0);
#endif
if (unsignedp) if (unsignedp)
comparison = unsigned_condition (comparison); comparison = unsigned_condition (comparison);
......
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