diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-02-13 01:55:37 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-02-13 01:55:37 +0000 |
commit | 85afca2d2a2079910420c66eb86d43d9628f3c39 (patch) | |
tree | 3d8ced1bf10347b4692e3a1210b4de3fd48c5e58 /gcc/dojump.c | |
parent | 275e0b851a75e5e68a4a74aaaa48b307d826fdbb (diff) | |
download | gcc-85afca2d2a2079910420c66eb86d43d9628f3c39.tar.gz |
PR middle-end/25724
* dojump.c (do_jump): Call do_compare_rtx_and_jump.
(do_jump_parts_zero_rtx): New function renamed from
do_jump_parts_equality_rtx. Made static. Add a mode argument.
(do_jump_parts_equality_rtx): New function split out from
do_jump_parts_equality. Old implementation renamed as above.
Call do_jump_parts_zero_rtx if either operand is zero.
(do_jump_parts_equality): Call do_jump_parts_equality_rtx to
do all of the heavy lifting.
(do_compare_rtx_and_jump): Handle multi-word comparisons by
calling either do_jump_by_parts_greater_rtx or
do_jump_by_parts_equality_rtx.
* expr.h (do_jump_by_parts_equality_rtx): Remove prototype.
* expmed.c (do_cmp_and_jump): Now multi-word optimization has
moved to do_compare_rtx_and_jump, call it directly.
* stmt.c (do_jump_if_equal): Remove static prototype. Add a
mode argument. Call do_compare_rtx_and_jump.
(emit_case_nodes): Update calls to do_jump_if_equal.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110906 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/dojump.c')
-rw-r--r-- | gcc/dojump.c | 188 |
1 files changed, 121 insertions, 67 deletions
diff --git a/gcc/dojump.c b/gcc/dojump.c index e214091510e..86dc6f4a6c4 100644 --- a/gcc/dojump.c +++ b/gcc/dojump.c @@ -1,6 +1,6 @@ /* Convert tree expression to rtl instructions, for GNU compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GCC. @@ -586,38 +586,20 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label) normal: temp = expand_normal (exp); do_pending_stack_adjust (); - - if (GET_CODE (temp) == CONST_INT - || (GET_CODE (temp) == CONST_DOUBLE && GET_MODE (temp) == VOIDmode) - || GET_CODE (temp) == LABEL_REF) - { - rtx target = temp == const0_rtx ? if_false_label : if_true_label; - if (target) - emit_jump (target); - } - else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT - && ! can_compare_p (NE, GET_MODE (temp), ccp_jump)) - /* Note swapping the labels gives us not-equal. */ - do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label); - else + /* The RTL optimizers prefer comparisons against pseudos. */ + if (GET_CODE (temp) == SUBREG) { - gcc_assert (GET_MODE (temp) != VOIDmode); - - /* The RTL optimizers prefer comparisons against pseudos. */ - if (GET_CODE (temp) == SUBREG) - { - /* Compare promoted variables in their promoted mode. */ - if (SUBREG_PROMOTED_VAR_P (temp) - && REG_P (XEXP (temp, 0))) - temp = XEXP (temp, 0); - else - temp = copy_to_reg (temp); - } - do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)), - NE, TYPE_UNSIGNED (TREE_TYPE (exp)), - GET_MODE (temp), NULL_RTX, - if_false_label, if_true_label); + /* Compare promoted variables in their promoted mode. */ + if (SUBREG_PROMOTED_VAR_P (temp) + && REG_P (XEXP (temp, 0))) + temp = XEXP (temp, 0); + else + temp = copy_to_reg (temp); } + do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)), + NE, TYPE_UNSIGNED (TREE_TYPE (exp)), + GET_MODE (temp), NULL_RTX, + if_false_label, if_true_label); } if (drop_through_label) @@ -695,43 +677,17 @@ do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0, if (drop_through_label) emit_label (drop_through_label); } - -/* Given an EQ_EXPR expression EXP for values too wide to be compared - with one insn, test the comparison and jump to the appropriate label. */ - -static void -do_jump_by_parts_equality (tree exp, rtx if_false_label, rtx if_true_label) -{ - rtx op0 = expand_normal (TREE_OPERAND (exp, 0)); - rtx op1 = expand_normal (TREE_OPERAND (exp, 1)); - enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); - int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); - int i; - rtx drop_through_label = 0; - - if (! if_false_label) - drop_through_label = if_false_label = gen_label_rtx (); - - for (i = 0; i < nwords; i++) - do_compare_rtx_and_jump (operand_subword_force (op0, i, mode), - operand_subword_force (op1, i, mode), - EQ, TYPE_UNSIGNED (TREE_TYPE (exp)), - word_mode, NULL_RTX, if_false_label, NULL_RTX); - - if (if_true_label) - emit_jump (if_true_label); - if (drop_through_label) - emit_label (drop_through_label); -} -/* Jump according to whether OP0 is 0. - We assume that OP0 has an integer mode that is too wide - for the available compare insns. */ +/* Jump according to whether OP0 is 0. We assume that OP0 has an integer + mode, MODE, that is too wide for the available compare insns. Either + Either (but not both) of IF_TRUE_LABEL and IF_FALSE_LABEL may be NULL_RTX + to indicate drop through. */ -void -do_jump_by_parts_equality_rtx (rtx op0, rtx if_false_label, rtx if_true_label) +static void +do_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0, + rtx if_false_label, rtx if_true_label) { - int nwords = GET_MODE_SIZE (GET_MODE (op0)) / UNITS_PER_WORD; + int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD; rtx part; int i; rtx drop_through_label = 0; @@ -771,6 +727,58 @@ do_jump_by_parts_equality_rtx (rtx op0, rtx if_false_label, rtx if_true_label) if (drop_through_label) emit_label (drop_through_label); } + +/* Test for the equality of two RTX expressions OP0 and OP1 in mode MODE, + where MODE is an integer mode too wide to be compared with one insn. + Either (but not both) of IF_TRUE_LABEL and IF_FALSE_LABEL may be NULL_RTX + to indicate drop through. */ + +static void +do_jump_by_parts_equality_rtx (enum machine_mode mode, rtx op0, rtx op1, + rtx if_false_label, rtx if_true_label) +{ + int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); + rtx drop_through_label = 0; + int i; + + if (op1 == const0_rtx) + { + do_jump_by_parts_zero_rtx (mode, op0, if_false_label, if_true_label); + return; + } + else if (op0 == const0_rtx) + { + do_jump_by_parts_zero_rtx (mode, op1, if_false_label, if_true_label); + return; + } + + if (! if_false_label) + drop_through_label = if_false_label = gen_label_rtx (); + + for (i = 0; i < nwords; i++) + do_compare_rtx_and_jump (operand_subword_force (op0, i, mode), + operand_subword_force (op1, i, mode), + EQ, 0, word_mode, NULL_RTX, + if_false_label, NULL_RTX); + + if (if_true_label) + emit_jump (if_true_label); + if (drop_through_label) + emit_label (drop_through_label); +} + +/* Given an EQ_EXPR expression EXP for values too wide to be compared + with one insn, test the comparison and jump to the appropriate label. */ + +static void +do_jump_by_parts_equality (tree exp, rtx if_false_label, rtx if_true_label) +{ + rtx op0 = expand_normal (TREE_OPERAND (exp, 0)); + rtx op1 = expand_normal (TREE_OPERAND (exp, 1)); + enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); + do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label, + if_true_label); +} /* Generate code for a comparison of OP0 and OP1 with rtx code CODE. MODE is the machine mode of the comparison, not of the result. @@ -886,14 +894,60 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU); } + if (! if_true_label) { dummy_true_label = 1; if_true_label = gen_label_rtx (); } - emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, - if_true_label); + if (GET_MODE_CLASS (mode) == MODE_INT + && ! can_compare_p (code, mode, ccp_jump)) + { + switch (code) + { + case LTU: + do_jump_by_parts_greater_rtx (mode, 1, op1, op0, + if_false_label, if_true_label); + break; + + case LEU: + do_jump_by_parts_greater_rtx (mode, 1, op0, op1, + if_true_label, if_false_label); + break; + + case LT: + do_jump_by_parts_greater_rtx (mode, 0, op1, op0, + if_false_label, if_true_label); + break; + + case GT: + do_jump_by_parts_greater_rtx (mode, 0, op0, op1, + if_false_label, if_true_label); + break; + + case GE: + do_jump_by_parts_greater_rtx (mode, 0, op1, op0, + if_true_label, if_false_label); + break; + + case EQ: + do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label, + if_true_label); + break; + + case NE: + do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label, + if_false_label); + break; + + default: + gcc_unreachable (); + } + } + else + emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, + if_true_label); if (if_false_label) emit_jump (if_false_label); |