re PR middle-end/25724 (Emits call to __cmpdi2 for long long comparison in switches)

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.

From-SVN: r110906
This commit is contained in:
Roger Sayle 2006-02-13 01:55:37 +00:00 committed by Roger Sayle
parent c0c84a897e
commit feb0478035
5 changed files with 161 additions and 146 deletions

View File

@ -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

View File

@ -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. */
/* 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. */
static void
do_jump_by_parts_equality (tree exp, rtx if_false_label, rtx if_true_label)
do_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0,
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. */
void
do_jump_by_parts_equality_rtx (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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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),