aboutsummaryrefslogtreecommitdiff
path: root/gcc/dojump.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2006-02-13 01:55:37 +0000
committerRoger Sayle <roger@eyesopen.com>2006-02-13 01:55:37 +0000
commit5955de9ecb97c9ff3401a5663f95f884235248e3 (patch)
tree3d8ced1bf10347b4692e3a1210b4de3fd48c5e58 /gcc/dojump.c
parent20c2a91c3d8698387c626bb87f49bea75c188db1 (diff)
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: https://gcc.gnu.org/svn/gcc/trunk@110906 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/dojump.c')
-rw-r--r--gcc/dojump.c188
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);