summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2006-02-13 01:55:37 +0000
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2006-02-13 01:55:37 +0000
commit85afca2d2a2079910420c66eb86d43d9628f3c39 (patch)
tree3d8ced1bf10347b4692e3a1210b4de3fd48c5e58
parent275e0b851a75e5e68a4a74aaaa48b307d826fdbb (diff)
downloadgcc-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/ChangeLog21
-rw-r--r--gcc/dojump.c188
-rw-r--r--gcc/expmed.c65
-rw-r--r--gcc/expr.h3
-rw-r--r--gcc/stmt.c30
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),