OSDN Git Service

PR 33870
[pf3gnuchains/gcc-fork.git] / gcc / stmt.c
index 3bb4f42..f1be5e0 100644 (file)
@@ -1,13 +1,13 @@
 /* Expands front end tree to back end RTL for GCC
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
 /* 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, 2007
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* This file handles the generation of rtl code from tree structure
    above the level of expressions, using subroutines in exp*.c and emit-rtl.c.
 
 /* This file handles the generation of rtl code from tree structure
    above the level of expressions, using subroutines in exp*.c and emit-rtl.c.
@@ -50,6 +49,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "optabs.h"
 #include "target.h"
 #include "regs.h"
 #include "optabs.h"
 #include "target.h"
 #include "regs.h"
+#include "alloc-pool.h"
 \f
 /* Functions and data structures for expanding case statements.  */
 
 \f
 /* Functions and data structures for expanding case statements.  */
 
@@ -80,7 +80,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    For very small, suitable switch statements, we can generate a series
    of simple bit test and branches instead.  */
 
    For very small, suitable switch statements, we can generate a series
    of simple bit test and branches instead.  */
 
-struct case_node GTY(())
+struct case_node
 {
   struct case_node     *left;  /* Left son in binary tree */
   struct case_node     *right; /* Right son in binary tree; also node chain */
 {
   struct case_node     *left;  /* Left son in binary tree */
   struct case_node     *right; /* Right son in binary tree; also node chain */
@@ -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 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 *);
 static int estimate_case_costs (case_node_ptr);
 static bool lshift_cheap_p (void);
 static int case_bit_test_cmp (const void *, const void *);
@@ -123,7 +122,7 @@ static int node_has_high_bound (case_node_ptr, tree);
 static int node_is_bounded (case_node_ptr, tree);
 static void emit_case_nodes (rtx, case_node_ptr, rtx, tree);
 static struct case_node *add_case_node (struct case_node *, tree,
 static int node_is_bounded (case_node_ptr, tree);
 static void emit_case_nodes (rtx, case_node_ptr, rtx, tree);
 static struct case_node *add_case_node (struct case_node *, tree,
-                                       tree, tree, tree);
+                                        tree, tree, tree, alloc_pool);
 
 \f
 /* Return the rtx-label that corresponds to a LABEL_DECL,
 
 \f
 /* Return the rtx-label that corresponds to a LABEL_DECL,
@@ -261,15 +260,16 @@ n_occurrences (int c, const char *s)
    insn is volatile; don't optimize it.  */
 
 static void
    insn is volatile; don't optimize it.  */
 
 static void
-expand_asm (tree string, int vol)
+expand_asm_loc (tree string, int vol, location_t locus)
 {
   rtx body;
 
   if (TREE_CODE (string) == ADDR_EXPR)
     string = TREE_OPERAND (string, 0);
 
 {
   rtx body;
 
   if (TREE_CODE (string) == ADDR_EXPR)
     string = TREE_OPERAND (string, 0);
 
-  body = gen_rtx_ASM_INPUT (VOIDmode,
-                           ggc_strdup (TREE_STRING_POINTER (string)));
+  body = gen_rtx_ASM_INPUT_loc (VOIDmode,
+                               ggc_strdup (TREE_STRING_POINTER (string)),
+                               locus);
 
   MEM_VOLATILE_P (body) = vol;
 
 
   MEM_VOLATILE_P (body) = vol;
 
@@ -568,25 +568,20 @@ decl_overlaps_hard_reg_set_p (tree *declp, int *walk_subtrees ATTRIBUTE_UNUSED,
   tree decl = *declp;
   const HARD_REG_SET *regs = data;
 
   tree decl = *declp;
   const HARD_REG_SET *regs = data;
 
-  if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
+  if (TREE_CODE (decl) == VAR_DECL)
     {
     {
-      if (DECL_REGISTER (decl)
+      if (DECL_HARD_REGISTER (decl)
          && REG_P (DECL_RTL (decl))
          && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
        {
          rtx reg = DECL_RTL (decl);
          && REG_P (DECL_RTL (decl))
          && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
        {
          rtx reg = DECL_RTL (decl);
-         unsigned int regno;
-
-         for (regno = REGNO (reg);
-              regno < (REGNO (reg)
-                       + hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
-              regno++)
-           if (TEST_HARD_REG_BIT (*regs, regno))
-             return decl;
+
+         if (overlaps_hard_reg_set_p (*regs, GET_MODE (reg), REGNO (reg)))
+           return decl;
        }
       walk_subtrees = 0;
     }
        }
       walk_subtrees = 0;
     }
-  else if (TYPE_P (decl))
+  else if (TYPE_P (decl) || TREE_CODE (decl) == PARM_DECL)
     walk_subtrees = 0;
   return NULL_TREE;
 }
     walk_subtrees = 0;
   return NULL_TREE;
 }
@@ -694,7 +689,11 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
   CLEAR_HARD_REG_SET (clobbered_regs);
   for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
     {
   CLEAR_HARD_REG_SET (clobbered_regs);
   for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
     {
-      const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
+      const char *regname;
+
+      if (TREE_VALUE (tail) == error_mark_node)
+       return;
+      regname = TREE_STRING_POINTER (TREE_VALUE (tail));
 
       i = decode_reg_name (regname);
       if (i >= 0 || i == -4)
 
       i = decode_reg_name (regname);
       if (i >= 0 || i == -4)
@@ -882,9 +881,13 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
 
       val = TREE_VALUE (tail);
       type = TREE_TYPE (val);
 
       val = TREE_VALUE (tail);
       type = TREE_TYPE (val);
+      /* EXPAND_INITIALIZER will not generate code for valid initializer
+        constants, but will still generate code for other types of operand.
+        This is the behavior we want for constant constraints.  */
       op = expand_expr (val, NULL_RTX, VOIDmode,
       op = expand_expr (val, NULL_RTX, VOIDmode,
-                       (allows_mem && !allows_reg
-                        ? EXPAND_MEMORY : EXPAND_NORMAL));
+                       allows_reg ? EXPAND_NORMAL
+                       : allows_mem ? EXPAND_MEMORY
+                       : EXPAND_INITIALIZER);
 
       /* Never pass a CONCAT to an ASM.  */
       if (GET_CODE (op) == CONCAT)
 
       /* Never pass a CONCAT to an ASM.  */
       if (GET_CODE (op) == CONCAT)
@@ -1075,6 +1078,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
     if (real_output_rtx[i])
       emit_move_insn (real_output_rtx[i], output_rtx[i]);
 
     if (real_output_rtx[i])
       emit_move_insn (real_output_rtx[i], output_rtx[i]);
 
+  cfun->has_asm_statement = 1;
   free_temp_slots ();
 }
 
   free_temp_slots ();
 }
 
@@ -1087,7 +1091,7 @@ expand_asm_expr (tree exp)
 
   if (ASM_INPUT_P (exp))
     {
 
   if (ASM_INPUT_P (exp))
     {
-      expand_asm (ASM_STRING (exp), ASM_VOLATILE_P (exp));
+      expand_asm_loc (ASM_STRING (exp), ASM_VOLATILE_P (exp), input_location);
       return;
     }
 
       return;
     }
 
@@ -1111,7 +1115,7 @@ expand_asm_expr (tree exp)
     {
       if (o[i] != TREE_VALUE (tail))
        {
     {
       if (o[i] != TREE_VALUE (tail))
        {
-         expand_assignment (o[i], TREE_VALUE (tail));
+         expand_assignment (o[i], TREE_VALUE (tail), false);
          free_temp_slots ();
 
          /* Restore the original value so that it's correct the next
          free_temp_slots ();
 
          /* Restore the original value so that it's correct the next
@@ -1354,7 +1358,10 @@ expand_expr_stmt (tree exp)
   rtx value;
   tree type;
 
   rtx value;
   tree type;
 
-  value = expand_expr (exp, const0_rtx, VOIDmode, 0);
+  value = expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
+  if (GIMPLE_TUPLE_P (exp))
+    type = void_type_node;
+  else
   type = TREE_TYPE (exp);
 
   /* If all we do is reference a volatile value in memory,
   type = TREE_TYPE (exp);
 
   /* If all we do is reference a volatile value in memory,
@@ -1386,7 +1393,7 @@ expand_expr_stmt (tree exp)
    (potential) location of the expression.  */
 
 int
    (potential) location of the expression.  */
 
 int
-warn_if_unused_value (tree exp, location_t locus)
+warn_if_unused_value (const_tree exp, location_t locus)
 {
  restart:
   if (TREE_USED (exp) || TREE_NO_WARNING (exp))
 {
  restart:
   if (TREE_USED (exp) || TREE_NO_WARNING (exp))
@@ -1408,12 +1415,14 @@ warn_if_unused_value (tree exp, location_t locus)
     case PREDECREMENT_EXPR:
     case POSTDECREMENT_EXPR:
     case MODIFY_EXPR:
     case PREDECREMENT_EXPR:
     case POSTDECREMENT_EXPR:
     case MODIFY_EXPR:
+    case GIMPLE_MODIFY_STMT:
     case INIT_EXPR:
     case TARGET_EXPR:
     case CALL_EXPR:
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
     case EXIT_EXPR:
     case INIT_EXPR:
     case TARGET_EXPR:
     case CALL_EXPR:
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
     case EXIT_EXPR:
+    case VA_ARG_EXPR:
       return 0;
 
     case BIND_EXPR:
       return 0;
 
     case BIND_EXPR:
@@ -1466,11 +1475,11 @@ warn_if_unused_value (tree exp, location_t locus)
       /* If this is an expression which has no operands, there is no value
         to be unused.  There are no such language-independent codes,
         but front ends may define such.  */
       /* If this is an expression which has no operands, there is no value
         to be unused.  There are no such language-independent codes,
         but front ends may define such.  */
-      if (EXPRESSION_CLASS_P (exp) && TREE_CODE_LENGTH (TREE_CODE (exp)) == 0)
+      if (EXPRESSION_CLASS_P (exp) && TREE_OPERAND_LENGTH (exp) == 0)
        return 0;
 
     warn:
        return 0;
 
     warn:
-      warning (0, "%Hvalue computed is not used", &locus);
+      warning (OPT_Wunused_value, "%Hvalue computed is not used", &locus);
       return 1;
     }
 }
       return 1;
     }
 }
@@ -1575,10 +1584,10 @@ expand_return (tree retval)
       expand_null_return ();
       return;
     }
       expand_null_return ();
       return;
     }
-  else if ((TREE_CODE (retval) == MODIFY_EXPR
+  else if ((TREE_CODE (retval) == GIMPLE_MODIFY_STMT
            || TREE_CODE (retval) == INIT_EXPR)
            || TREE_CODE (retval) == INIT_EXPR)
-          && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
-    retval_rhs = TREE_OPERAND (retval, 1);
+          && TREE_CODE (GENERIC_TREE_OPERAND (retval, 0)) == RESULT_DECL)
+    retval_rhs = GENERIC_TREE_OPERAND (retval, 1);
   else
     retval_rhs = retval;
 
   else
     retval_rhs = retval;
 
@@ -1597,7 +1606,7 @@ expand_return (tree retval)
      (and in expand_call).  */
 
   else if (retval_rhs != 0
      (and in expand_call).  */
 
   else if (retval_rhs != 0
-          && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
+          && TYPE_MODE (GENERIC_TREE_TYPE (retval_rhs)) == BLKmode
           && REG_P (result_rtl))
     {
       int i;
           && REG_P (result_rtl))
     {
       int i;
@@ -1715,7 +1724,7 @@ expand_return (tree retval)
       tree nt = build_qualified_type (ot, TYPE_QUALS (ot) | TYPE_QUAL_CONST);
 
       val = assign_temp (nt, 0, 0, 1);
       tree nt = build_qualified_type (ot, TYPE_QUALS (ot) | TYPE_QUAL_CONST);
 
       val = assign_temp (nt, 0, 0, 1);
-      val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
+      val = expand_expr (retval_rhs, val, GET_MODE (val), EXPAND_NORMAL);
       val = force_not_mem (val);
       /* Return the calculated value.  */
       expand_value_return (val);
       val = force_not_mem (val);
       /* Return the calculated value.  */
       expand_value_return (val);
@@ -1723,7 +1732,7 @@ expand_return (tree retval)
   else
     {
       /* No hard reg used; calculate value into hard return reg.  */
   else
     {
       /* No hard reg used; calculate value into hard return reg.  */
-      expand_expr (retval, const0_rtx, VOIDmode, 0);
+      expand_expr (retval, const0_rtx, VOIDmode, EXPAND_NORMAL);
       expand_value_return (result_rtl);
     }
 }
       expand_value_return (result_rtl);
     }
 }
@@ -1739,7 +1748,7 @@ expand_return (tree retval)
    *that* node in turn will point to the relevant FUNCTION_DECL node.  */
 
 int
    *that* node in turn will point to the relevant FUNCTION_DECL node.  */
 
 int
-is_body_block (tree stmt)
+is_body_block (const_tree stmt)
 {
   if (lang_hooks.no_body_blocks)
     return 0;
 {
   if (lang_hooks.no_body_blocks)
     return 0;
@@ -1822,12 +1831,10 @@ expand_nl_goto_receiver (void)
     emit_insn (gen_nonlocal_goto_receiver ());
 #endif
 
     emit_insn (gen_nonlocal_goto_receiver ());
 #endif
 
-  /* @@@ This is a kludge.  Not all machine descriptions define a blockage
-     insn, but we must not allow the code we just generated to be reordered
-     by scheduling.  Specifically, the update of the frame pointer must
-     happen immediately, not later.  So emit an ASM_INPUT to act as blockage
-     insn.  */
-  emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
+  /* We must not allow the code we just generated to be reordered by
+     scheduling.  Specifically, the update of the frame pointer must
+     happen immediately, not later.  */
+  emit_insn (gen_blockage ());
 }
 \f
 /* Generate RTL for the automatic variable declaration DECL.
 }
 \f
 /* Generate RTL for the automatic variable declaration DECL.
@@ -1892,19 +1899,11 @@ expand_decl (tree decl)
 
       /* Note if the object is a user variable.  */
       if (!DECL_ARTIFICIAL (decl))
 
       /* Note if the object is a user variable.  */
       if (!DECL_ARTIFICIAL (decl))
-       {
          mark_user_reg (DECL_RTL (decl));
 
          mark_user_reg (DECL_RTL (decl));
 
-         /* Trust user variables which have a pointer type to really
-            be pointers.  Do not trust compiler generated temporaries
-            as our type system is totally busted as it relates to
-            pointer arithmetic which translates into lots of compiler
-            generated objects with pointer types, but which are not really
-            pointers.  */
-         if (POINTER_TYPE_P (type))
-           mark_reg_pointer (DECL_RTL (decl),
-                             TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
-       }
+      if (POINTER_TYPE_P (type))
+       mark_reg_pointer (DECL_RTL (decl),
+                         TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
     }
 
   else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
     }
 
   else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
@@ -2069,7 +2068,7 @@ expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED,
 
 static struct case_node *
 add_case_node (struct case_node *head, tree type, tree low, tree high,
 
 static struct case_node *
 add_case_node (struct case_node *head, tree type, tree low, tree high,
-              tree label)
+               tree label, alloc_pool case_node_pool)
 {
   tree min_value, max_value;
   struct case_node *r;
 {
   tree min_value, max_value;
   struct case_node *r;
@@ -2121,7 +2120,7 @@ add_case_node (struct case_node *head, tree type, tree low, tree high,
 
 
   /* Add this label to the chain.  Make sure to drop overflow flags.  */
 
 
   /* Add this label to the chain.  Make sure to drop overflow flags.  */
-  r = ggc_alloc (sizeof (struct case_node));
+  r = (struct case_node *) pool_alloc (case_node_pool);
   r->low = build_int_cst_wide (TREE_TYPE (low), TREE_INT_CST_LOW (low),
                               TREE_INT_CST_HIGH (low));
   r->high = build_int_cst_wide (TREE_TYPE (high), TREE_INT_CST_LOW (high),
   r->low = build_int_cst_wide (TREE_TYPE (low), TREE_INT_CST_LOW (low),
                               TREE_INT_CST_HIGH (low));
   r->high = build_int_cst_wide (TREE_TYPE (high), TREE_INT_CST_LOW (high),
@@ -2137,7 +2136,7 @@ add_case_node (struct case_node *head, tree type, tree low, tree high,
 
 /* By default, enable case bit tests on targets with ashlsi3.  */
 #ifndef CASE_USE_BIT_TESTS
 
 /* By default, enable case bit tests on targets with ashlsi3.  */
 #ifndef CASE_USE_BIT_TESTS
-#define CASE_USE_BIT_TESTS  (ashl_optab->handlers[word_mode].insn_code \
+#define CASE_USE_BIT_TESTS  (optab_handler (ashl_optab, word_mode)->insn_code \
                             != CODE_FOR_nothing)
 #endif
 
                             != CODE_FOR_nothing)
 #endif
 
@@ -2287,7 +2286,7 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
 #define HAVE_tablejump 0
 #endif
 
 #define HAVE_tablejump 0
 #endif
 
-/* Terminate a case (Pascal) or switch (C) statement
+/* Terminate a case (Pascal/Ada) or switch (C) statement
    in which ORIG_INDEX is the expression to be tested.
    If ORIG_TYPE is not NULL, it is the original ORIG_INDEX
    type as given in the source before any compiler conversions.
    in which ORIG_INDEX is the expression to be tested.
    If ORIG_TYPE is not NULL, it is the original ORIG_INDEX
    type as given in the source before any compiler conversions.
@@ -2304,7 +2303,7 @@ expand_case (tree exp)
   rtx table_label;
   int ncases;
   rtx *labelvec;
   rtx table_label;
   int ncases;
   rtx *labelvec;
-  int i, fail;
+  int i;
   rtx before_case, end, lab;
 
   tree vec = SWITCH_LABELS (exp);
   rtx before_case, end, lab;
 
   tree vec = SWITCH_LABELS (exp);
@@ -2324,6 +2323,10 @@ expand_case (tree exp)
   /* Label to jump to if no case matches.  */
   tree default_label_decl;
 
   /* Label to jump to if no case matches.  */
   tree default_label_decl;
 
+  alloc_pool case_node_pool = create_alloc_pool ("struct case_node pool",
+                                                 sizeof (struct case_node),
+                                                 100);
+
   /* The switch body is lowered in gimplify.c, we should never have
      switches with a non-NULL SWITCH_BODY here.  */
   gcc_assert (!SWITCH_BODY (exp));
   /* The switch body is lowered in gimplify.c, we should never have
      switches with a non-NULL SWITCH_BODY here.  */
   gcc_assert (!SWITCH_BODY (exp));
@@ -2349,26 +2352,24 @@ expand_case (tree exp)
 
       for (i = TREE_VEC_LENGTH (vec) - 1; --i >= 0; )
        {
 
       for (i = TREE_VEC_LENGTH (vec) - 1; --i >= 0; )
        {
+         tree low, high;
          elt = TREE_VEC_ELT (vec, i);
          elt = TREE_VEC_ELT (vec, i);
-         gcc_assert (CASE_LOW (elt));
-         case_list = add_case_node (case_list, index_type,
-                                    CASE_LOW (elt), CASE_HIGH (elt),
-                                    CASE_LABEL (elt));
-       }
 
 
+         low = CASE_LOW (elt);
+         gcc_assert (low);
+         high = CASE_HIGH (elt);
 
 
-      /* Make sure start points to something that won't need any
-        transformation before the end of this function.  */
-      start = get_last_insn ();
-      if (! NOTE_P (start))
-       {
-         emit_note (NOTE_INSN_DELETED);
-         start = get_last_insn ();
+         /* Discard empty ranges.  */
+         if (high && INT_CST_LT (high, low))
+           continue;
+
+         case_list = add_case_node (case_list, index_type, low, high,
+                                     CASE_LABEL (elt), case_node_pool);
        }
 
        }
 
-      default_label = label_rtx (default_label_decl);
 
 
-      before_case = get_last_insn ();
+      before_case = start = get_last_insn ();
+      default_label = label_rtx (default_label_decl);
 
       /* Get upper and lower bounds of case values.  */
 
 
       /* Get upper and lower bounds of case values.  */
 
@@ -2414,6 +2415,7 @@ expand_case (tree exp)
       if (count == 0)
        {
          emit_jump (default_label);
       if (count == 0)
        {
          emit_jump (default_label);
+          free_alloc_pool (case_node_pool);
          return;
        }
 
          return;
        }
 
@@ -2580,29 +2582,21 @@ expand_case (tree exp)
 
       before_case = NEXT_INSN (before_case);
       end = get_last_insn ();
 
       before_case = NEXT_INSN (before_case);
       end = get_last_insn ();
-      fail = squeeze_notes (&before_case, &end);
-      gcc_assert (!fail);
       reorder_insns (before_case, end, start);
     }
 
   free_temp_slots ();
       reorder_insns (before_case, end, start);
     }
 
   free_temp_slots ();
+  free_alloc_pool (case_node_pool);
 }
 
 }
 
-/* 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
 
 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
 }
 \f
 /* Not all case values are encountered equally.  This function
@@ -2944,6 +2938,10 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
   enum machine_mode mode = GET_MODE (index);
   enum machine_mode imode = TYPE_MODE (index_type);
 
   enum machine_mode mode = GET_MODE (index);
   enum machine_mode imode = TYPE_MODE (index_type);
 
+  /* Handle indices detected as constant during RTL expansion.  */
+  if (mode == VOIDmode)
+    mode = imode;
+
   /* See if our parents have already tested everything for us.
      If they have, emit an unconditional jump for this node.  */
   if (node_is_bounded (node, index_type))
   /* See if our parents have already tested everything for us.
      If they have, emit an unconditional jump for this node.  */
   if (node_is_bounded (node, index_type))
@@ -2954,7 +2952,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.  */
 
       /* 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),
                        convert_modes (mode, imode,
                                       expand_normal (node->low),
                                       unsignedp),
@@ -3007,7 +3005,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
 
              /* See if the value matches what the right hand side
                 wants.  */
 
              /* 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),
                                convert_modes (mode, imode,
                                               expand_normal (node->right->low),
                                               unsignedp),
@@ -3016,7 +3014,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
 
              /* See if the value matches what the left hand side
                 wants.  */
 
              /* 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),
                                convert_modes (mode, imode,
                                               expand_normal (node->left->low),
                                               unsignedp),
@@ -3082,7 +3080,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.  */
            /* 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),
                              convert_modes
                              (mode, imode,
                               expand_normal (node->right->low),
@@ -3113,7 +3111,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.  */
            /* 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),
                              convert_modes
                              (mode, imode,
                               expand_normal (node->left->low),