re PR middle-end/25724 (Emits call to __cmpdi2 for long long comparison in switches)
authorRoger Sayle <roger@eyesopen.com>
Mon, 13 Feb 2006 01:55:37 +0000 (01:55 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Mon, 13 Feb 2006 01:55:37 +0000 (01:55 +0000)
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

gcc/ChangeLog
gcc/dojump.c
gcc/expmed.c
gcc/expr.h
gcc/stmt.c

index d68c547052cb01b0003ca40ebce9378c1fb82cbb..18ea30d7b340406554c158da5ff1bbacb8b3d0fa 100644 (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
index e214091510e03918d656eaf04b1dacd28dce5b81..86dc6f4a6c4ec9c7207d9ac34bceb90f4cbbe989 100644 (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.  */
-
-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);
-}
 \f
-/* 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);
+}
 \f
 /* 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);
index a12c65d14440161d97a8e130a8d391561515591e..7d77587e6e61c6b535e0406d2938be6e04df609d 100644 (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,
 }
 \f
 /* 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);
 }
index 2be41005942a25c942a678d86b06f9d384c1d5a9..f1cf081b195d1e34d2d10008c26d0f361179f3e4 100644 (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);
 
index 3bb4f42c2da8597d36c55d7f59ae6e947446b9e8..be192169e004358c331a4708e02e40d177a5972d 100644 (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);
 }
 \f
 /* 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),