diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2009-06-28 17:03:03 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gcc.gnu.org> | 2009-06-28 17:03:03 +0000 |
commit | 45475a3fb2c32ca082c07e633b2ded9ead70177e (patch) | |
tree | 6cb46c8b1432e5b2682ebbe1c480966ef11ded79 /gcc | |
parent | 495499daead6ed7050db2af715fabd4f472595cd (diff) | |
download | gcc-45475a3fb2c32ca082c07e633b2ded9ead70177e.zip gcc-45475a3fb2c32ca082c07e633b2ded9ead70177e.tar.gz gcc-45475a3fb2c32ca082c07e633b2ded9ead70177e.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/dojump.c | 25 | ||||
-rw-r--r-- | gcc/expmed.c | 105 | ||||
-rw-r--r-- | gcc/optabs.c | 10 |
4 files changed, 88 insertions, 62 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 96bd8cf..7076397 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ 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. (do_store_flag): Drop support for TRUTH_NOT_EXPR. Use emit_store_flag_force. diff --git a/gcc/dojump.c b/gcc/dojump.c index 131aaed..3685ff5 100644 --- a/gcc/dojump.c +++ b/gcc/dojump.c @@ -920,16 +920,27 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, { if (GET_MODE_CLASS (mode) == MODE_FLOAT && ! 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. */ - && (code != ORDERED && code != UNORDERED) + /* Never split ORDERED and UNORDERED. These must be implemented. */ + && (code != ORDERED && code != UNORDERED) - /* Split a floating-point comparison if we can jump on other - conditions... */ - && (have_insn_for (COMPARE, mode) + /* Split a floating-point comparison if we can jump on other + conditions... */ + && (have_insn_for (COMPARE, mode) - /* ... or if there is no libcall for it. */ - || code_to_optab[code] == NULL)) + /* ... or if there is no libcall for it. */ + || code_to_optab[code] == NULL)) { enum rtx_code first_code; bool and_them = split_comparison (code, mode, &first_code, &code); diff --git a/gcc/expmed.c b/gcc/expmed.c index 9c76a6d..841f94b 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -5115,11 +5115,40 @@ expand_and (enum machine_mode mode, rtx op0, rtx op1, rtx target) /* Helper function for emit_store_flag. */ static rtx -emit_store_flag_1 (rtx target, rtx subtarget, enum machine_mode mode, - int normalizep) +emit_store_flag_1 (rtx target, enum insn_code icode, enum rtx_code code, + 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 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) target = gen_reg_rtx (GET_MODE (subtarget)); @@ -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 interpreted in MODE, we can do this conversion as unsigned, which 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, - (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) + (GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT) && 0 == (STORE_FLAG_VALUE & ((HOST_WIDE_INT) 1 - << (GET_MODE_BITSIZE (mode) -1)))); + << (GET_MODE_BITSIZE (result_mode) -1)))); op0 = target; - mode = target_mode; + result_mode = target_mode; } else op0 = subtarget; @@ -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 the comparison this way to avoid a compiler-time warning. */ 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 it hard to use a value of just the sign bit due to ANSI integer 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 - & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))) - op0 = expand_shift (RSHIFT_EXPR, mode, op0, - size_int (GET_MODE_BITSIZE (mode) - 1), subtarget, + & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (result_mode) - 1)))) + op0 = expand_shift (RSHIFT_EXPR, result_mode, op0, + size_int (GET_MODE_BITSIZE (result_mode) - 1), subtarget, normalizep == 1); else { 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) - 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 (target_mode != mode) + if (target_mode != result_mode) { convert_move (target, op0, 0); return target; @@ -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 mode_class mclass; enum rtx_code rcode; + enum rtx_code scode; rtx tem, trueval; rtx last; - rtx pattern, comparison; if (unsignedp) code = unsigned_condition (code); + scode = swap_condition (code); /* If one operand is constant, make it the second one. Only do this 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, icode = optab_handler (cstore_optab, optab_mode)->insn_code; if (icode != CODE_FOR_nothing) { - rtx x, y; - enum machine_mode result_mode - = insn_data[(int) icode].operand[0].mode; - do_pending_stack_adjust (); - last = get_last_insn (); + tem = emit_store_flag_1 (target, icode, code, mode, compare_mode, + unsignedp, op0, op1, normalizep); + if (tem) + return tem; - x = prepare_operand (icode, op0, 2, mode, compare_mode, unsignedp); - y = prepare_operand (icode, op1, 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)) + if (GET_MODE_CLASS (mode) == MODE_FLOAT) { - 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) - { - emit_insn (pattern); - return emit_store_flag_1 (target, subtarget, result_mode, - normalizep); + tem = emit_store_flag_1 (target, icode, scode, mode, compare_mode, + unsignedp, op1, op0, normalizep); + if (tem) + return tem; } - - delete_insns_since (last); break; } } diff --git a/gcc/optabs.c b/gcc/optabs.c index d76d41e..16eb4dd 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4280,18 +4280,18 @@ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size, rtx test; /* 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; comparison = swap_condition (comparison); } -#ifdef HAVE_cc0 - /* If OP0 is still a constant, then both X and Y must be constants. - Force X into a register to create canonical RTL. */ + /* 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 + to create canonical RTL. */ if (CONSTANT_P (op0)) op0 = force_reg (mode, op0); -#endif if (unsignedp) comparison = unsigned_condition (comparison); |