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 | |
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
-rw-r--r-- | gcc/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/dojump.c | 188 | ||||
-rw-r--r-- | gcc/expmed.c | 65 | ||||
-rw-r--r-- | gcc/expr.h | 3 | ||||
-rw-r--r-- | gcc/stmt.c | 30 |
5 files changed, 161 insertions, 146 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d68c547052c..18ea30d7b34 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2006-02-12 Roger Sayle <roger@eyesopen.com> + + 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. + 2006-02-12 Zdenek Dvorak <dvorakz@suse.cz> PR rtl-optimization/26225 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); diff --git a/gcc/expmed.c b/gcc/expmed.c index a12c65d1444..7d77587e6e6 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -1,7 +1,8 @@ /* Medium-level subroutines: convert bit-field store and extract and shifts, multiplies and divides to rtl instructions. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. This file is part of GCC. @@ -5564,66 +5565,14 @@ emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1, } /* Perform possibly multi-word comparison and conditional jump to LABEL - if ARG1 OP ARG2 true where ARG1 and ARG2 are of mode MODE - - The algorithm is based on the code in expr.c:do_jump. - - Note that this does not perform a general comparison. Only - variants generated within expmed.c are correctly handled, others - could be handled if needed. */ + if ARG1 OP ARG2 true where ARG1 and ARG2 are of mode MODE. This is + now a thin wrapper around do_compare_rtx_and_jump. */ static void do_cmp_and_jump (rtx arg1, rtx arg2, enum rtx_code op, enum machine_mode mode, rtx label) { - /* If this mode is an integer too wide to compare properly, - compare word by word. Rely on cse to optimize constant cases. */ - - if (GET_MODE_CLASS (mode) == MODE_INT - && ! can_compare_p (op, mode, ccp_jump)) - { - rtx label2 = gen_label_rtx (); - - switch (op) - { - case LTU: - do_jump_by_parts_greater_rtx (mode, 1, arg2, arg1, label2, label); - break; - - case LEU: - do_jump_by_parts_greater_rtx (mode, 1, arg1, arg2, label, label2); - break; - - case LT: - do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label2, label); - break; - - case GT: - do_jump_by_parts_greater_rtx (mode, 0, arg1, arg2, label2, label); - break; - - case GE: - do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label, label2); - break; - - /* do_jump_by_parts_equality_rtx compares with zero. Luckily - that's the only equality operations we do */ - case EQ: - gcc_assert (arg2 == const0_rtx && mode == GET_MODE(arg1)); - do_jump_by_parts_equality_rtx (arg1, label2, label); - break; - - case NE: - gcc_assert (arg2 == const0_rtx && mode == GET_MODE(arg1)); - do_jump_by_parts_equality_rtx (arg1, label, label2); - break; - - default: - gcc_unreachable (); - } - - emit_label (label2); - } - else - emit_cmp_and_jump_insns (arg1, arg2, op, NULL_RTX, mode, 0, label); + int unsignedp = (op == LTU || op == LEU || op == GTU || op == GEU); + do_compare_rtx_and_jump (arg1, arg2, op, unsignedp, mode, + NULL_RTX, NULL_RTX, label); } diff --git a/gcc/expr.h b/gcc/expr.h index 2be41005942..f1cf081b195 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -1,6 +1,6 @@ /* Definitions for code generation pass of GNU compiler. Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GCC. @@ -743,7 +743,6 @@ extern void init_all_optabs (void); /* Call this to initialize an optab function entry. */ extern rtx init_one_libfunc (const char *); -extern void do_jump_by_parts_equality_rtx (rtx, rtx, rtx); extern void do_jump_by_parts_greater_rtx (enum machine_mode, int, rtx, rtx, rtx, rtx); diff --git a/gcc/stmt.c b/gcc/stmt.c index 3bb4f42c2da..be192169e00 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -1,6 +1,6 @@ /* Expands front end tree to back end RTL for GCC Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GCC. @@ -112,7 +112,6 @@ static bool check_unique_operand_names (tree, tree); static char *resolve_operand_name_1 (char *, tree, tree); static void expand_null_return_1 (void); static void expand_value_return (rtx); -static void do_jump_if_equal (rtx, rtx, rtx, int); static int estimate_case_costs (case_node_ptr); static bool lshift_cheap_p (void); static int case_bit_test_cmp (const void *, const void *); @@ -2588,21 +2587,14 @@ expand_case (tree exp) free_temp_slots (); } -/* Generate code to jump to LABEL if OP1 and OP2 are equal. */ +/* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE. */ static void -do_jump_if_equal (rtx op1, rtx op2, rtx label, int unsignedp) +do_jump_if_equal (enum machine_mode mode, rtx op0, rtx op1, rtx label, + int unsignedp) { - if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT) - { - if (op1 == op2) - emit_jump (label); - } - else - emit_cmp_and_jump_insns (op1, op2, EQ, NULL_RTX, - (GET_MODE (op1) == VOIDmode - ? GET_MODE (op2) : GET_MODE (op1)), - unsignedp, label); + do_compare_rtx_and_jump (op0, op1, EQ, unsignedp, mode, + NULL_RTX, NULL_RTX, label); } /* Not all case values are encountered equally. This function @@ -2954,7 +2946,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label, /* Node is single valued. First see if the index expression matches this node and then check our children, if any. */ - do_jump_if_equal (index, + do_jump_if_equal (mode, index, convert_modes (mode, imode, expand_normal (node->low), unsignedp), @@ -3007,7 +2999,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label, /* See if the value matches what the right hand side wants. */ - do_jump_if_equal (index, + do_jump_if_equal (mode, index, convert_modes (mode, imode, expand_normal (node->right->low), unsignedp), @@ -3016,7 +3008,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label, /* See if the value matches what the left hand side wants. */ - do_jump_if_equal (index, + do_jump_if_equal (mode, index, convert_modes (mode, imode, expand_normal (node->left->low), unsignedp), @@ -3082,7 +3074,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label, /* We cannot process node->right normally since we haven't ruled out the numbers less than this node's value. So handle node->right explicitly. */ - do_jump_if_equal (index, + do_jump_if_equal (mode, index, convert_modes (mode, imode, expand_normal (node->right->low), @@ -3113,7 +3105,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label, /* We cannot process node->left normally since we haven't ruled out the numbers less than this node's value. So handle node->left explicitly. */ - do_jump_if_equal (index, + do_jump_if_equal (mode, index, convert_modes (mode, imode, expand_normal (node->left->low), |