From 45475a3fb2c32ca082c07e633b2ded9ead70177e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 28 Jun 2009 17:03:03 +0000 Subject: [PATCH] dojump.c (do_compare_rtx_and_jump): Try swapping the condition for floating point modes. 2009-06-28 Paolo Bonzini * 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 --- gcc/ChangeLog | 10 +++++ gcc/dojump.c | 25 ++++++++---- gcc/expmed.c | 105 ++++++++++++++++++++++++++------------------------ gcc/optabs.c | 10 ++--- 4 files changed, 88 insertions(+), 62 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 96bd8cf1a713..70763970f2a6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2009-06-28 Paolo Bonzini + + * 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 * expr.c (expand_expr_real_1): Just use do_store_flag. diff --git a/gcc/dojump.c b/gcc/dojump.c index 131aaed977ff..3685ff513d00 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; + } - /* Never split ORDERED and UNORDERED. These must be implemented. */ - && (code != ORDERED && code != UNORDERED) + else if (GET_MODE_CLASS (mode) == MODE_FLOAT + && ! can_compare_p (code, mode, ccp_jump) - /* Split a floating-point comparison if we can jump on other - conditions... */ - && (have_insn_for (COMPARE, mode) + /* Never split ORDERED and UNORDERED. These must be implemented. */ + && (code != ORDERED && code != UNORDERED) - /* ... or if there is no libcall for it. */ - || code_to_optab[code] == NULL)) + /* 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)) { 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 9c76a6d9fb7c..841f94b4c927 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; + tem = emit_store_flag_1 (target, icode, scode, mode, compare_mode, + unsignedp, op1, op0, normalizep); + if (tem) + return tem; } - - 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); - } - - delete_insns_since (last); break; } } diff --git a/gcc/optabs.c b/gcc/optabs.c index d76d41e4b5b7..16eb4dd3dbba 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);