OSDN Git Service

2008-03-13 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / stmt.c
index 6d3043b..aacb184 100644 (file)
@@ -1,12 +1,13 @@
 /* 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 Free Software Foundation, Inc.
+   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
-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
@@ -15,23 +16,13 @@ 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
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, 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.
-   It also creates the rtl expressions for parameters and auto variables
-   and has full responsibility for allocating stack slots.
-
    The functions whose names start with `expand_' are called by the
-   parser to generate RTL instructions for various kinds of constructs.
-
-   Some control and binding constructs require calling several such
-   functions at different times.  For example, a simple if-then
-   is expanded by calling `expand_start_cond' (with the condition-expression
-   as argument) before parsing the then-clause and calling `expand_end_cond'
-   after parsing the then-clause.  */
+   expander to generate RTL instructions for various kinds of constructs.  */
 
 #include "config.h"
 #include "system.h"
@@ -39,6 +30,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm.h"
 
 #include "rtl.h"
+#include "hard-reg-set.h"
 #include "tree.h"
 #include "tm_p.h"
 #include "flags.h"
@@ -47,8 +39,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "insn-config.h"
 #include "expr.h"
 #include "libfuncs.h"
-#include "hard-reg-set.h"
-#include "loop.h"
 #include "recog.h"
 #include "machmode.h"
 #include "toplev.h"
@@ -59,6 +49,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "optabs.h"
 #include "target.h"
 #include "regs.h"
+#include "alloc-pool.h"
 \f
 /* Functions and data structures for expanding case statements.  */
 
@@ -89,7 +80,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    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 */
@@ -113,163 +104,15 @@ static int cost_table_initialized;
    is unsigned.  */
 #define COST_TABLE(I)  cost_table_[(unsigned HOST_WIDE_INT) ((I) + 1)]
 \f
-/* Stack of control and binding constructs we are currently inside.
-
-   These constructs begin when you call `expand_start_WHATEVER'
-   and end when you call `expand_end_WHATEVER'.  This stack records
-   info about how the construct began that tells the end-function
-   what to do.  It also may provide information about the construct
-   to alter the behavior of other constructs within the body.
-   For example, they may affect the behavior of C `break' and `continue'.
-
-   Each construct gets one `struct nesting' object.
-   All of these objects are chained through the `all' field.
-   `nesting_stack' points to the first object (innermost construct).
-   The position of an entry on `nesting_stack' is in its `depth' field.
-
-   Each type of construct has its own individual stack.
-   For example, loops have `cond_stack'.  Each object points to the
-   next object of the same type through the `next' field.
-
-   Some constructs are visible to `break' exit-statements and others
-   are not.  Which constructs are visible depends on the language.
-   Therefore, the data structure allows each construct to be visible
-   or not, according to the args given when the construct is started.
-   The construct is visible if the `exit_label' field is non-null.
-   In that case, the value should be a CODE_LABEL rtx.  */
-
-struct nesting GTY(())
-{
-  struct nesting *all;
-  struct nesting *next;
-  int depth;
-  rtx exit_label;
-  enum nesting_desc {
-    COND_NESTING,
-    BLOCK_NESTING,
-    CASE_NESTING
-  } desc;
-  union nesting_u
-    {
-      /* For conds (if-then and if-then-else statements).  */
-      struct nesting_cond
-       {
-         /* Label for the end of the if construct.
-            There is none if EXITFLAG was not set
-            and no `else' has been seen yet.  */
-         rtx endif_label;
-         /* Label for the end of this alternative.
-            This may be the end of the if or the next else/elseif.  */
-         rtx next_label;
-       } GTY ((tag ("COND_NESTING"))) cond;
-      /* For variable binding contours.  */
-      struct nesting_block
-       {
-         /* Sequence number of this binding contour within the function,
-            in order of entry.  */
-         int block_start_count;
-         /* The NOTE that starts this contour.
-            Used by expand_goto to check whether the destination
-            is within each contour or not.  */
-         rtx first_insn;
-         /* The saved target_temp_slot_level from our outer block.
-            We may reset target_temp_slot_level to be the level of
-            this block, if that is done, target_temp_slot_level
-            reverts to the saved target_temp_slot_level at the very
-            end of the block.  */
-         int block_target_temp_slot_level;
-       } GTY ((tag ("BLOCK_NESTING"))) block;
-      /* For switch (C) or case (Pascal) statements.  */
-      struct nesting_case
-       {
-         /* The insn after which the case dispatch should finally
-            be emitted.  Zero for a dummy.  */
-         rtx start;
-         /* A list of case labels; it is first built as an AVL tree.
-            During expand_end_case, this is converted to a list, and may be
-            rearranged into a nearly balanced binary tree.  */
-         struct case_node *case_list;
-         /* Label to jump to if no case matches.  */
-         tree default_label;
-         /* The expression to be dispatched on.  */
-         tree index_expr;
-       } GTY ((tag ("CASE_NESTING"))) case_stmt;
-    } GTY ((desc ("%1.desc"))) data;
-};
-
-/* Allocate and return a new `struct nesting'.  */
-
-#define ALLOC_NESTING() ggc_alloc (sizeof (struct nesting))
-
-/* Pop the nesting stack element by element until we pop off
-   the element which is at the top of STACK.
-   Update all the other stacks, popping off elements from them
-   as we pop them from nesting_stack.  */
-
-#define POPSTACK(STACK)                                        \
-do { struct nesting *target = STACK;                   \
-     struct nesting *this;                             \
-     do { this = nesting_stack;                                \
-         if (cond_stack == this)                       \
-           cond_stack = cond_stack->next;              \
-         if (block_stack == this)                      \
-           block_stack = block_stack->next;            \
-         if (case_stack == this)                       \
-           case_stack = case_stack->next;              \
-         nesting_depth = nesting_stack->depth - 1;     \
-         nesting_stack = this->all; }                  \
-     while (this != target); } while (0)
-\f
-
-struct stmt_status GTY(())
-{
-  /* Chain of all pending binding contours.  */
-  struct nesting * x_block_stack;
-
-  /* If any new stacks are added here, add them to POPSTACKS too.  */
-
-  /* Chain of all pending conditional statements.  */
-  struct nesting * x_cond_stack;
-
-  /* Chain of all pending case or switch statements.  */
-  struct nesting * x_case_stack;
-
-  /* Separate chain including all of the above,
-     chained through the `all' field.  */
-  struct nesting * x_nesting_stack;
-
-  /* Number of entries on nesting_stack now.  */
-  int x_nesting_depth;
-
-  /* Number of binding contours started so far in this function.  */
-  int x_block_start_count;
-
-  /* Location of last line-number note, whether we actually
-     emitted it or not.  */
-  location_t x_emit_locus;
-};
-
-#define block_stack (cfun->stmt->x_block_stack)
-#define cond_stack (cfun->stmt->x_cond_stack)
-#define case_stack (cfun->stmt->x_case_stack)
-#define nesting_stack (cfun->stmt->x_nesting_stack)
-#define nesting_depth (cfun->stmt->x_nesting_depth)
-#define current_block_start_count (cfun->stmt->x_block_start_count)
-#define emit_locus (cfun->stmt->x_emit_locus)
-
 static int n_occurrences (int, const char *);
-static bool decl_conflicts_with_clobbers_p (tree, const HARD_REG_SET);
+static bool tree_conflicts_with_clobbers_p (tree, HARD_REG_SET *);
 static void expand_nl_goto_receiver (void);
 static bool check_operand_nalternatives (tree, tree);
 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 enum br_predictor return_prediction (rtx);
-static rtx shift_return_value (rtx);
 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 same_case_target_p (rtx, rtx);
 static bool lshift_cheap_p (void);
 static int case_bit_test_cmp (const void *, const void *);
 static void emit_case_bit_tests (tree, tree, tree, tree, case_node_ptr, rtx);
@@ -278,39 +121,9 @@ static int node_has_low_bound (case_node_ptr, tree);
 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);
-\f
-void
-init_stmt_for_function (void)
-{
-  cfun->stmt = ggc_alloc_cleared (sizeof (struct stmt_status));
-}
-\f
-/* Record the current file and line.  Called from emit_line_note.  */
-
-void
-set_file_and_line_for_stmt (location_t location)
-{
-  /* If we're outputting an inline function, and we add a line note,
-     there may be no CFUN->STMT information.  So, there's no need to
-     update it.  */
-  if (cfun->stmt)
-    emit_locus = location;
-}
+static struct case_node *add_case_node (struct case_node *, tree,
+                                        tree, tree, tree, alloc_pool);
 
-/* Emit a no-op instruction.  */
-
-void
-emit_nop (void)
-{
-  rtx last_insn;
-
-  last_insn = get_last_insn ();
-  if (!optimize
-      && (LABEL_P (last_insn)
-         || (NOTE_P (last_insn)
-             && prev_real_insn (last_insn) == 0)))
-    emit_insn (gen_nop ());
-}
 \f
 /* Return the rtx-label that corresponds to a LABEL_DECL,
    creating it if necessary.  */
@@ -318,8 +131,7 @@ emit_nop (void)
 rtx
 label_rtx (tree label)
 {
-  if (TREE_CODE (label) != LABEL_DECL)
-    abort ();
+  gcc_assert (TREE_CODE (label) == LABEL_DECL);
 
   if (!DECL_RTL_SET_P (label))
     {
@@ -341,8 +153,7 @@ force_label_rtx (tree label)
   tree function = decl_function_context (label);
   struct function *p;
 
-  if (!function)
-    abort ();
+  gcc_assert (function);
 
   if (function != current_function_decl)
     p = find_function_data (function);
@@ -370,7 +181,7 @@ emit_jump (rtx label)
 void
 expand_computed_goto (tree exp)
 {
-  rtx x = expand_expr (exp, NULL_RTX, VOIDmode, 0);
+  rtx x = expand_normal (exp);
 
   x = convert_memory_address (Pmode, x);
 
@@ -411,7 +222,7 @@ expand_label (tree label)
 
   if (FORCED_LABEL (label))
     forced_labels = gen_rtx_EXPR_LIST (VOIDmode, label_r, forced_labels);
-      
+
   if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
     maybe_set_first_label_num (label_r);
 }
@@ -427,8 +238,7 @@ expand_goto (tree label)
   /* Check for a nonlocal goto to a containing function.  Should have
      gotten translated to __builtin_nonlocal_goto.  */
   tree context = decl_function_context (label);
-  if (context != 0 && context != current_function_decl)
-    abort ();
+  gcc_assert (!context || context == current_function_decl);
 #endif
 
   emit_jump (label_rtx (label));
@@ -449,15 +259,17 @@ n_occurrences (int c, const char *s)
    or an ADDR_EXPR containing a STRING_CST.  VOL nonzero means the
    insn is volatile; don't optimize it.  */
 
-void
-expand_asm (tree string, int vol)
+static void
+expand_asm_loc (tree string, int vol, location_t locus)
 {
   rtx body;
 
   if (TREE_CODE (string) == ADDR_EXPR)
     string = TREE_OPERAND (string, 0);
 
-  body = gen_rtx_ASM_INPUT (VOIDmode, TREE_STRING_POINTER (string));
+  body = gen_rtx_ASM_INPUT_loc (VOIDmode,
+                               ggc_strdup (TREE_STRING_POINTER (string)),
+                               locus);
 
   MEM_VOLATILE_P (body) = vol;
 
@@ -502,7 +314,7 @@ parse_output_constraint (const char **constraint_p, int operand_num,
      message.  */
   if (!p)
     {
-      error ("output operand constraint lacks `='");
+      error ("output operand constraint lacks %<=%>");
       return false;
     }
 
@@ -511,13 +323,14 @@ parse_output_constraint (const char **constraint_p, int operand_num,
   *is_inout = (*p == '+');
 
   /* Canonicalize the output constraint so that it begins with `='.  */
-  if (p != constraint || is_inout)
+  if (p != constraint || *is_inout)
     {
       char *buf;
       size_t c_len = strlen (constraint);
 
       if (p != constraint)
-       warning ("output constraint `%c' for operand %d is not at the beginning",
+       warning (0, "output constraint %qc for operand %d "
+                "is not at the beginning",
                 *p, operand_num);
 
       /* Make a copy of the constraint.  */
@@ -539,13 +352,14 @@ parse_output_constraint (const char **constraint_p, int operand_num,
       {
       case '+':
       case '=':
-       error ("operand constraint contains incorrectly positioned '+' or '='");
+       error ("operand constraint contains incorrectly positioned "
+              "%<+%> or %<=%>");
        return false;
 
       case '%':
        if (operand_num + 1 == ninputs + noutputs)
          {
-           error ("`%%' constraint used with last operand");
+           error ("%<%%%> constraint used with last operand");
            return false;
          }
        break;
@@ -635,7 +449,7 @@ parse_input_constraint (const char **constraint_p, int input_num,
       case '+':  case '=':  case '&':
        if (constraint == orig_constraint)
          {
-           error ("input operand constraint contains `%c'", constraint[j]);
+           error ("input operand constraint contains %qc", constraint[j]);
            return false;
          }
        break;
@@ -644,7 +458,7 @@ parse_input_constraint (const char **constraint_p, int input_num,
        if (constraint == orig_constraint
            && input_num + 1 == ninputs - ninout)
          {
-           error ("`%%' constraint used with last operand");
+           error ("%<%%%> constraint used with last operand");
            return false;
          }
        break;
@@ -715,7 +529,7 @@ parse_input_constraint (const char **constraint_p, int input_num,
       default:
        if (! ISALPHA (constraint[j]))
          {
-           error ("invalid punctuation `%c' in constraint", constraint[j]);
+           error ("invalid punctuation %qc in constraint", constraint[j]);
            return false;
          }
        if (REG_CLASS_FROM_CONSTRAINT (constraint[j], constraint + j)
@@ -739,70 +553,69 @@ parse_input_constraint (const char **constraint_p, int input_num,
       }
 
   if (saw_match && !*allows_reg)
-    warning ("matching constraint does not allow a register");
+    warning (0, "matching constraint does not allow a register");
 
   return true;
 }
 
-/* INPUT is one of the input operands from EXPR, an ASM_EXPR.  Returns true
-   if it is an operand which must be passed in memory (i.e. an "m"
-   constraint), false otherwise.  */
+/* Return DECL iff there's an overlap between *REGS and DECL, where DECL
+   can be an asm-declared register.  Called via walk_tree.  */
 
-bool
-asm_op_is_mem_input (tree input, tree expr)
+static tree
+decl_overlaps_hard_reg_set_p (tree *declp, int *walk_subtrees ATTRIBUTE_UNUSED,
+                             void *data)
 {
-  const char *constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (input)));
-  tree outputs = ASM_OUTPUTS (expr);
-  int noutputs = list_length (outputs);
-  const char **constraints
-    = (const char **) alloca ((noutputs) * sizeof (const char *));
-  int i = 0;
-  bool allows_mem, allows_reg;
-  tree t;
+  tree decl = *declp;
+  const HARD_REG_SET *regs = data;
 
-  /* Collect output constraints.  */
-  for (t = outputs; t ; t = TREE_CHAIN (t), i++)
-    constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
+  if (TREE_CODE (decl) == VAR_DECL)
+    {
+      if (DECL_HARD_REGISTER (decl)
+         && REG_P (DECL_RTL (decl))
+         && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
+       {
+         rtx reg = DECL_RTL (decl);
+
+         if (overlaps_hard_reg_set_p (*regs, GET_MODE (reg), REGNO (reg)))
+           return decl;
+       }
+      walk_subtrees = 0;
+    }
+  else if (TYPE_P (decl) || TREE_CODE (decl) == PARM_DECL)
+    walk_subtrees = 0;
+  return NULL_TREE;
+}
 
-  /* We pass 0 for input_num, ninputs and ninout; they are only used for
-     error checking which will be done at expand time.  */
-  parse_input_constraint (&constraint, 0, 0, noutputs, 0, constraints,
-                         &allows_mem, &allows_reg);
-  return (!allows_reg && allows_mem);
+/* If there is an overlap between *REGS and DECL, return the first overlap
+   found.  */
+tree
+tree_overlaps_hard_reg_set (tree decl, HARD_REG_SET *regs)
+{
+  return walk_tree (&decl, decl_overlaps_hard_reg_set_p, regs, NULL);
 }
 
 /* Check for overlap between registers marked in CLOBBERED_REGS and
-   anything inappropriate in DECL.  Emit error and return TRUE for error,
-   FALSE for ok.  */
+   anything inappropriate in T.  Emit error and return the register
+   variable definition for error, NULL_TREE for ok.  */
 
 static bool
-decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs)
+tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
 {
   /* Conflicts between asm-declared register variables and the clobber
      list are not allowed.  */
-  if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
-      && DECL_REGISTER (decl)
-      && REG_P (DECL_RTL (decl))
-      && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
+  tree overlap = tree_overlaps_hard_reg_set (t, clobbered_regs);
+
+  if (overlap)
     {
-      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 (clobbered_regs, regno))
-         {
-           error ("asm-specifier for variable `%s' conflicts with asm clobber list",
-                  IDENTIFIER_POINTER (DECL_NAME (decl)));
+      error ("asm-specifier for variable %qs conflicts with asm clobber list",
+            IDENTIFIER_POINTER (DECL_NAME (overlap)));
 
-           /* Reset registerness to stop multiple errors emitted for a
-              single variable.  */
-           DECL_REGISTER (decl) = 0;
-           return true;
-         }
+      /* Reset registerness to stop multiple errors emitted for a single
+        variable.  */
+      DECL_REGISTER (overlap) = 0;
+      return true;
     }
+
   return false;
 }
 
@@ -823,7 +636,7 @@ decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs)
 
    VOL nonzero means the insn is volatile; don't optimize it.  */
 
-void
+static void
 expand_asm_operands (tree string, tree outputs, tree inputs,
                     tree clobbers, int vol, location_t locus)
 {
@@ -868,7 +681,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
      Case in point is when the i386 backend moved from cc0 to a hard reg --
      maintaining source-level compatibility means automatically clobbering
      the flags register.  */
-  clobbers = targetm.md_asm_clobbers (clobbers);
+  clobbers = targetm.md_asm_clobbers (outputs, inputs, clobbers);
 
   /* Count the number of meaningful clobbered registers, ignoring what
      we would ignore later.  */
@@ -876,21 +689,25 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
   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)
        ++nclobbers;
       else if (i == -2)
-       error ("unknown register name `%s' in `asm'", regname);
+       error ("unknown register name %qs in %<asm%>", regname);
 
       /* Mark clobbered registers.  */
       if (i >= 0)
         {
-         /* Clobbering the PIC register is an error */
+         /* Clobbering the PIC register is an error */
          if (i == (int) PIC_OFFSET_TABLE_REGNUM)
            {
-             error ("PIC register `%s' clobbered in `asm'", regname);
+             error ("PIC register %qs clobbered in %<asm%>", regname);
              return;
            }
 
@@ -937,7 +754,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
   ninputs += ninout;
   if (ninputs + noutputs > MAX_RECOG_OPERANDS)
     {
-      error ("more than %d operands in `asm'", MAX_RECOG_OPERANDS);
+      error ("more than %d operands in %<asm%>", MAX_RECOG_OPERANDS);
       return;
     }
 
@@ -971,11 +788,12 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
       bool allows_reg;
       bool allows_mem;
       rtx op;
+      bool ok;
 
-      if (!parse_output_constraint (&constraints[i], i, ninputs,
+      ok = parse_output_constraint (&constraints[i], i, ninputs,
                                    noutputs, &allows_mem, &allows_reg,
-                                   &is_inout))
-       abort ();
+                                   &is_inout);
+      gcc_assert (ok);
 
       /* If an output operand is not a decl or indirect ref and our constraint
         allows a register, make a temporary to act as an intermediate.
@@ -1025,7 +843,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
          inout_opnum[ninout++] = i;
        }
 
-      if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
+      if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
        clobber_conflict_found = 1;
     }
 
@@ -1037,7 +855,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
 
   body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
                                : GET_MODE (output_rtx[0])),
-                              TREE_STRING_POINTER (string),
+                              ggc_strdup (TREE_STRING_POINTER (string)),
                               empty_string, 0, argvec, constraintvec,
                               locus);
 
@@ -1052,19 +870,24 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
       const char *constraint;
       tree val, type;
       rtx op;
+      bool ok;
 
       constraint = constraints[i + noutputs];
-      if (! parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
-                                   constraints, &allows_mem, &allows_reg))
-       abort ();
+      ok = parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
+                                  constraints, &allows_mem, &allows_reg);
+      gcc_assert (ok);
 
       generating_concat_p = 0;
 
       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,
-                       (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)
@@ -1074,10 +897,10 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
 
       if (asm_operand_ok (op, constraint) <= 0)
        {
-         if (allows_reg)
+         if (allows_reg && TYPE_MODE (type) != BLKmode)
            op = force_reg (TYPE_MODE (type), op);
          else if (!allows_mem)
-           warning ("asm operand %d probably doesn't match constraints",
+           warning (0, "asm operand %d probably doesn%'t match constraints",
                     i + noutputs);
          else if (MEM_P (op))
            {
@@ -1087,7 +910,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
            }
          else
            {
-             warning ("use of memory input without lvalue in "
+             warning (0, "use of memory input without lvalue in "
                       "asm operand %d is deprecated", i + noutputs);
 
              if (CONSTANT_P (op))
@@ -1117,9 +940,10 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
       ASM_OPERANDS_INPUT (body, i) = op;
 
       ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, i)
-       = gen_rtx_ASM_INPUT (TYPE_MODE (type), constraints[i + noutputs]);
+       = gen_rtx_ASM_INPUT (TYPE_MODE (type), 
+                            ggc_strdup (constraints[i + noutputs]));
 
-      if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
+      if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
        clobber_conflict_found = 1;
     }
 
@@ -1151,7 +975,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
 
   if (noutputs == 1 && nclobbers == 0)
     {
-      ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = constraints[0];
+      ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = ggc_strdup (constraints[0]);
       emit_insn (gen_rtx_SET (VOIDmode, output_rtx[0], body));
     }
 
@@ -1179,9 +1003,9 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
                           output_rtx[i],
                           gen_rtx_ASM_OPERANDS
                           (GET_MODE (output_rtx[i]),
-                           TREE_STRING_POINTER (string),
-                           constraints[i], i, argvec, constraintvec,
-                           locus));
+                           ggc_strdup (TREE_STRING_POINTER (string)),
+                           ggc_strdup (constraints[i]),
+                           i, argvec, constraintvec, locus));
 
          MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
        }
@@ -1254,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]);
 
+  cfun->has_asm_statement = 1;
   free_temp_slots ();
 }
 
@@ -1266,7 +1091,7 @@ expand_asm_expr (tree 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;
     }
 
@@ -1290,7 +1115,7 @@ expand_asm_expr (tree exp)
     {
       if (o[i] != TREE_VALUE (tail))
        {
-         expand_assignment (o[i], TREE_VALUE (tail), 0);
+         expand_assignment (o[i], TREE_VALUE (tail), false);
          free_temp_slots ();
 
          /* Restore the original value so that it's correct the next
@@ -1315,7 +1140,7 @@ check_operand_nalternatives (tree outputs, tree inputs)
 
       if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
        {
-         error ("too many alternatives in `asm'");
+         error ("too many alternatives in %<asm%>");
          return false;
        }
 
@@ -1327,7 +1152,8 @@ check_operand_nalternatives (tree outputs, tree inputs)
 
          if (n_occurrences (',', constraint) != nalternatives)
            {
-             error ("operand constraints for `asm' differ in number of alternatives");
+             error ("operand constraints for %<asm%> differ "
+                    "in number of alternatives");
              return false;
            }
 
@@ -1379,7 +1205,7 @@ check_unique_operand_names (tree outputs, tree inputs)
   return true;
 
  failure:
-  error ("duplicate asm operand name '%s'",
+  error ("duplicate asm operand name %qs",
         TREE_STRING_POINTER (TREE_PURPOSE (TREE_PURPOSE (i))));
   return false;
 }
@@ -1437,7 +1263,7 @@ resolve_asm_operand_names (tree string, tree outputs, tree inputs)
         than 999 operands.  */
       buffer = xstrdup (TREE_STRING_POINTER (string));
       p = buffer + (c - TREE_STRING_POINTER (string));
-      
+
       while ((p = strchr (p, '%')) != NULL)
        {
          if (p[1] == '[')
@@ -1505,7 +1331,7 @@ resolve_operand_name_1 (char *p, tree outputs, tree inputs)
     }
 
   *q = '\0';
-  error ("undefined named operand '%s'", p + 1);
+  error ("undefined named operand %qs", p + 1);
   op = 0;
  found:
 
@@ -1516,8 +1342,7 @@ resolve_operand_name_1 (char *p, tree outputs, tree inputs)
   p = strchr (p, '\0');
 
   /* Verify the no extra buffer space assumption.  */
-  if (p > q)
-    abort ();
+  gcc_assert (p <= q);
 
   /* Shift the rest of the buffer down to fill the gap.  */
   memmove (p, q + 1, strlen (q + 1) + 1);
@@ -1533,7 +1358,10 @@ expand_expr_stmt (tree exp)
   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,
@@ -1550,8 +1378,7 @@ expand_expr_stmt (tree exp)
 
          /* Compare the value with itself to reference it.  */
          emit_cmp_and_jump_insns (value, value, EQ,
-                                  expand_expr (TYPE_SIZE (type),
-                                               NULL_RTX, VOIDmode, 0),
+                                  expand_normal (TYPE_SIZE (type)),
                                   BLKmode, 0, lab);
          emit_label (lab);
        }
@@ -1562,14 +1389,14 @@ expand_expr_stmt (tree exp)
 }
 
 /* Warn if EXP contains any computations whose results are not used.
-   Return 1 if a warning is printed; 0 otherwise.  LOCUS is the 
+   Return 1 if a warning is printed; 0 otherwise.  LOCUS is the
    (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))
+  if (TREE_USED (exp) || TREE_NO_WARNING (exp))
     return 0;
 
   /* Don't warn about void constructs.  This includes casting to void,
@@ -1588,12 +1415,14 @@ warn_if_unused_value (tree exp, location_t locus)
     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 VA_ARG_EXPR:
       return 0;
 
     case BIND_EXPR:
@@ -1612,8 +1441,6 @@ warn_if_unused_value (tree exp, location_t locus)
       goto restart;
 
     case COMPOUND_EXPR:
-      if (TREE_NO_WARNING (exp))
-       return 0;
       if (warn_if_unused_value (TREE_OPERAND (exp, 0), locus))
        return 1;
       /* Let people do `(foo (), 0)' without a warning.  */
@@ -1622,27 +1449,12 @@ warn_if_unused_value (tree exp, location_t locus)
       exp = TREE_OPERAND (exp, 1);
       goto restart;
 
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case NON_LVALUE_EXPR:
-      /* Don't warn about conversions not explicit in the user's program.  */
-      if (TREE_NO_WARNING (exp))
+    case COND_EXPR:
+      /* If this is an expression with side effects, don't warn; this
+        case commonly appears in macro expansions.  */
+      if (TREE_SIDE_EFFECTS (exp))
        return 0;
-      /* Assignment to a cast usually results in a cast of a modify.
-        Don't complain about that.  There can be an arbitrary number of
-        casts before the modify, so we must loop until we find the first
-        non-cast expression and then test to see if that is a modify.  */
-      {
-       tree tem = TREE_OPERAND (exp, 0);
-
-       while (TREE_CODE (tem) == CONVERT_EXPR || TREE_CODE (tem) == NOP_EXPR)
-         tem = TREE_OPERAND (tem, 0);
-
-       if (TREE_CODE (tem) == MODIFY_EXPR || TREE_CODE (tem) == INIT_EXPR
-           || TREE_CODE (tem) == CALL_EXPR)
-         return 0;
-      }
-      goto maybe_warn;
+      goto warn;
 
     case INDIRECT_REF:
       /* Don't warn about automatic dereferencing of references, since
@@ -1656,127 +1468,21 @@ warn_if_unused_value (tree exp, location_t locus)
 
     default:
       /* Referencing a volatile value is a side effect, so don't warn.  */
-      if ((DECL_P (exp)
-          || TREE_CODE_CLASS (TREE_CODE (exp)) == 'r')
+      if ((DECL_P (exp) || REFERENCE_CLASS_P (exp))
          && TREE_THIS_VOLATILE (exp))
        return 0;
 
       /* 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 (TREE_CODE_CLASS (TREE_CODE (exp)) == 'e'
-         && TREE_CODE_LENGTH (TREE_CODE (exp)) == 0)
-       return 0;
-
-    maybe_warn:
-      /* If this is an expression with side effects, don't warn.  */
-      if (TREE_SIDE_EFFECTS (exp))
+      if (EXPRESSION_CLASS_P (exp) && TREE_OPERAND_LENGTH (exp) == 0)
        return 0;
 
-      warning ("%Hvalue computed is not used", &locus);
+    warn:
+      warning (OPT_Wunused_value, "%Hvalue computed is not used", &locus);
       return 1;
     }
 }
-\f
-/* Generate RTL for the start of an if-then.  COND is the expression
-   whose truth should be tested.
-
-   If EXITFLAG is nonzero, this conditional is visible to
-   `exit_something'.  */
-
-void
-expand_start_cond (tree cond, int exitflag)
-{
-  struct nesting *thiscond = ALLOC_NESTING ();
-
-  /* Make an entry on cond_stack for the cond we are entering.  */
-
-  thiscond->desc = COND_NESTING;
-  thiscond->next = cond_stack;
-  thiscond->all = nesting_stack;
-  thiscond->depth = ++nesting_depth;
-  thiscond->data.cond.next_label = gen_label_rtx ();
-  /* Before we encounter an `else', we don't need a separate exit label
-     unless there are supposed to be exit statements
-     to exit this conditional.  */
-  thiscond->exit_label = exitflag ? gen_label_rtx () : 0;
-  thiscond->data.cond.endif_label = thiscond->exit_label;
-  cond_stack = thiscond;
-  nesting_stack = thiscond;
-
-  do_jump (cond, thiscond->data.cond.next_label, NULL_RTX);
-}
-
-/* Generate RTL between then-clause and the elseif-clause
-   of an if-then-elseif-....  */
-
-void
-expand_start_elseif (tree cond)
-{
-  if (cond_stack->data.cond.endif_label == 0)
-    cond_stack->data.cond.endif_label = gen_label_rtx ();
-  emit_jump (cond_stack->data.cond.endif_label);
-  emit_label (cond_stack->data.cond.next_label);
-  cond_stack->data.cond.next_label = gen_label_rtx ();
-  do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX);
-}
-
-/* Generate RTL between the then-clause and the else-clause
-   of an if-then-else.  */
-
-void
-expand_start_else (void)
-{
-  if (cond_stack->data.cond.endif_label == 0)
-    cond_stack->data.cond.endif_label = gen_label_rtx ();
-
-  emit_jump (cond_stack->data.cond.endif_label);
-  emit_label (cond_stack->data.cond.next_label);
-  cond_stack->data.cond.next_label = 0;  /* No more _else or _elseif calls.  */
-}
-
-/* After calling expand_start_else, turn this "else" into an "else if"
-   by providing another condition.  */
-
-void
-expand_elseif (tree cond)
-{
-  cond_stack->data.cond.next_label = gen_label_rtx ();
-  do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX);
-}
-
-/* Generate RTL for the end of an if-then.
-   Pop the record for it off of cond_stack.  */
-
-void
-expand_end_cond (void)
-{
-  struct nesting *thiscond = cond_stack;
-
-  do_pending_stack_adjust ();
-  if (thiscond->data.cond.next_label)
-    emit_label (thiscond->data.cond.next_label);
-  if (thiscond->data.cond.endif_label)
-    emit_label (thiscond->data.cond.endif_label);
-
-  POPSTACK (cond_stack);
-}
-\f
-/* Return nonzero if we should preserve sub-expressions as separate
-   pseudos.  We never do so if we aren't optimizing.  We always do so
-   if -fexpensive-optimizations.  */
-
-int
-preserve_subexpressions_p (void)
-{
-  if (flag_expensive_optimizations)
-    return 1;
-
-  if (optimize == 0 || cfun == 0 || cfun->stmt == 0)
-    return 0;
-
-  return 1;
-}
 
 \f
 /* Generate RTL to return from the current function, with no value.
@@ -1811,87 +1517,15 @@ expand_naked_return (void)
   emit_jump (end_label);
 }
 
-/* Try to guess whether the value of return means error code.  */
-static enum br_predictor
-return_prediction (rtx val)
-{
-  /* Different heuristics for pointers and scalars.  */
-  if (POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
-    {
-      /* NULL is usually not returned.  */
-      if (val == const0_rtx)
-       return PRED_NULL_RETURN;
-    }
-  else
-    {
-      /* Negative return values are often used to indicate
-         errors.  */
-      if (GET_CODE (val) == CONST_INT
-         && INTVAL (val) < 0)
-       return PRED_NEGATIVE_RETURN;
-      /* Constant return values are also usually erors,
-         zero/one often mean booleans so exclude them from the
-        heuristics.  */
-      if (CONSTANT_P (val)
-         && (val != const0_rtx && val != const1_rtx))
-       return PRED_CONST_RETURN;
-    }
-  return PRED_NO_PREDICTION;
-}
-
-
-/* If the current function returns values in the most significant part
-   of a register, shift return value VAL appropriately.  The mode of
-   the function's return type is known not to be BLKmode.  */
-
-static rtx
-shift_return_value (rtx val)
-{
-  tree type;
-
-  type = TREE_TYPE (DECL_RESULT (current_function_decl));
-  if (targetm.calls.return_in_msb (type))
-    {
-      rtx target;
-      HOST_WIDE_INT shift;
-
-      target = DECL_RTL (DECL_RESULT (current_function_decl));
-      shift = (GET_MODE_BITSIZE (GET_MODE (target))
-              - BITS_PER_UNIT * int_size_in_bytes (type));
-      if (shift > 0)
-       val = expand_shift (LSHIFT_EXPR, GET_MODE (target),
-                           gen_lowpart (GET_MODE (target), val),
-                           build_int_2 (shift, 0), target, 1);
-    }
-  return val;
-}
-
-
 /* Generate RTL to return from the current function, with value VAL.  */
 
 static void
 expand_value_return (rtx val)
 {
-  rtx return_reg;
-  enum br_predictor pred;
-
-  if (flag_guess_branch_prob
-      && (pred = return_prediction (val)) != PRED_NO_PREDICTION)
-    {
-      /* Emit information for branch prediction.  */
-      rtx note;
-
-      note = emit_note (NOTE_INSN_PREDICTION);
-
-      NOTE_PREDICTION (note) = NOTE_PREDICT (pred, NOT_TAKEN);
-
-    }
-
-  return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
-
   /* Copy the value to the return location
      unless it's already there.  */
 
+  rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
   if (return_reg != val)
     {
       tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
@@ -1920,15 +1554,9 @@ expand_value_return (rtx val)
 static void
 expand_null_return_1 (void)
 {
-  rtx end_label;
-
   clear_pending_stack_adjust ();
   do_pending_stack_adjust ();
-
-  end_label = return_label;
-  if (end_label == 0)
-     end_label = return_label = gen_label_rtx ();
-  emit_jump (end_label);
+  emit_jump (return_label);
 }
 \f
 /* Generate RTL to evaluate the expression RETVAL and return it
@@ -1944,7 +1572,7 @@ expand_return (tree retval)
   /* If function wants no value, give it none.  */
   if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE)
     {
-      expand_expr (retval, NULL_RTX, VOIDmode, 0);
+      expand_normal (retval);
       expand_null_return ();
       return;
     }
@@ -1956,17 +1584,20 @@ expand_return (tree retval)
       expand_null_return ();
       return;
     }
-  else if (TREE_CODE (retval) == RESULT_DECL)
-    retval_rhs = retval;
-  else if ((TREE_CODE (retval) == MODIFY_EXPR
+  else if ((TREE_CODE (retval) == GIMPLE_MODIFY_STMT
            || 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;
 
   result_rtl = DECL_RTL (DECL_RESULT (current_function_decl));
 
+  /* If we are returning the RESULT_DECL, then the value has already
+     been stored into it, so we don't have to do anything special.  */
+  if (TREE_CODE (retval_rhs) == RESULT_DECL)
+    expand_value_return (result_rtl);
+
   /* If the result is an aggregate that is being returned in one (or more)
      registers, load the registers here.  The compiler currently can't handle
      copying a BLKmode value into registers.  We could put this code in a
@@ -1974,9 +1605,9 @@ expand_return (tree retval)
      call/return), but until this feature is generally usable it is kept here
      (and in expand_call).  */
 
-  if (retval_rhs != 0
-      && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
-      && REG_P (result_rtl))
+  else if (retval_rhs != 0
+          && TYPE_MODE (GENERIC_TREE_TYPE (retval_rhs)) == BLKmode
+          && REG_P (result_rtl))
     {
       int i;
       unsigned HOST_WIDE_INT bitpos, xbitpos;
@@ -1988,7 +1619,7 @@ expand_return (tree retval)
        = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)), BITS_PER_WORD);
       rtx *result_pseudos = alloca (sizeof (rtx) * n_regs);
       rtx result_reg, src = NULL_RTX, dst = NULL_RTX;
-      rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
+      rtx result_val = expand_normal (retval_rhs);
       enum machine_mode tmpmode, result_reg_mode;
 
       if (bytes == 0)
@@ -2061,9 +1692,8 @@ expand_return (tree retval)
            if (GET_MODE_SIZE (tmpmode) >= bytes)
              break;
 
-         /* No suitable mode found.  */
-         if (tmpmode == VOIDmode)
-           abort ();
+         /* A suitable mode should have been found.  */
+         gcc_assert (tmpmode != VOIDmode);
 
          PUT_MODE (result_rtl, tmpmode);
        }
@@ -2094,111 +1724,19 @@ expand_return (tree retval)
       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 (shift_return_value (val));
+      expand_value_return (val);
     }
   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);
     }
 }
 \f
-/* Generate the RTL code for entering a binding contour.
-   The variables are declared one by one, by calls to `expand_decl'.
-
-   FLAGS is a bitwise or of the following flags:
-
-     1 - Nonzero if this construct should be visible to
-         `exit_something'.
-
-     2 - Nonzero if this contour does not require a
-        NOTE_INSN_BLOCK_BEG note.  Virtually all calls from
-        language-independent code should set this flag because they
-        will not create corresponding BLOCK nodes.  (There should be
-        a one-to-one correspondence between NOTE_INSN_BLOCK_BEG notes
-        and BLOCKs.)  If this flag is set, MARK_ENDS should be zero
-        when expand_end_bindings is called.
-
-    If we are creating a NOTE_INSN_BLOCK_BEG note, a BLOCK may
-    optionally be supplied.  If so, it becomes the NOTE_BLOCK for the
-    note.  */
-
-void
-expand_start_bindings_and_block (int flags, tree block)
-{
-  struct nesting *thisblock = ALLOC_NESTING ();
-  rtx note;
-  int exit_flag = ((flags & 1) != 0);
-  int block_flag = ((flags & 2) == 0);
-
-  /* If a BLOCK is supplied, then the caller should be requesting a
-     NOTE_INSN_BLOCK_BEG note.  */
-  if (!block_flag && block)
-    abort ();
-
-  /* Create a note to mark the beginning of the block.  */
-  note = emit_note (NOTE_INSN_DELETED);
-
-  /* Make an entry on block_stack for the block we are entering.  */
-
-  thisblock->desc = BLOCK_NESTING;
-  thisblock->next = block_stack;
-  thisblock->all = nesting_stack;
-  thisblock->depth = ++nesting_depth;
-  thisblock->data.block.block_target_temp_slot_level = target_temp_slot_level;
-
-  /* When we insert instructions after the last unconditional cleanup,
-     we don't adjust last_insn.  That means that a later add_insn will
-     clobber the instructions we've just added.  The easiest way to
-     fix this is to just insert another instruction here, so that the
-     instructions inserted after the last unconditional cleanup are
-     never the last instruction.  */
-  emit_note (NOTE_INSN_DELETED);
-
-  thisblock->data.block.first_insn = note;
-  thisblock->data.block.block_start_count = ++current_block_start_count;
-  thisblock->exit_label = exit_flag ? gen_label_rtx () : 0;
-  block_stack = thisblock;
-  nesting_stack = thisblock;
-
-  /* Make a new level for allocating stack slots.  */
-  push_temp_slots ();
-}
-
-/* Specify the scope of temporaries created by TARGET_EXPRs.  Similar
-   to CLEANUP_POINT_EXPR, but handles cases when a series of calls to
-   expand_expr are made.  After we end the region, we know that all
-   space for all temporaries that were created by TARGET_EXPRs will be
-   destroyed and their space freed for reuse.  */
-
-void
-expand_start_target_temps (void)
-{
-  /* This is so that even if the result is preserved, the space
-     allocated will be freed, as we know that it is no longer in use.  */
-  push_temp_slots ();
-
-  /* Start a new binding layer that will keep track of all cleanup
-     actions to be performed.  */
-  expand_start_bindings (2);
-
-  target_temp_slot_level = temp_slot_level;
-}
-
-void
-expand_end_target_temps (void)
-{
-  expand_end_bindings (NULL_TREE, 0, 0);
-
-  /* This is so that even if the result is preserved, the space
-     allocated will be freed, as we know that it is no longer in use.  */
-  pop_temp_slots ();
-}
-
 /* Given a pointer to a BLOCK node return nonzero if (and only if) the node
    in question represents the outermost pair of curly braces (i.e. the "body
    block") of a function or method.
@@ -2210,7 +1748,7 @@ expand_end_target_temps (void)
    *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;
@@ -2231,15 +1769,6 @@ is_body_block (tree stmt)
   return 0;
 }
 
-/* Return an opaque pointer to the current nesting level, so frontend code
-   can check its own sanity.  */
-
-struct nesting *
-current_nesting_level (void)
-{
-  return cfun ? block_stack : 0;
-}
-
 /* Emit code to restore vital registers at the beginning of a nonlocal goto
    handler.  */
 static void
@@ -2302,76 +1831,10 @@ expand_nl_goto_receiver (void)
     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, ""));
-}
-
-/* Warn about any unused VARS (which may contain nodes other than
-   VAR_DECLs, but such nodes are ignored).  The nodes are connected
-   via the TREE_CHAIN field.  */
-
-void
-warn_about_unused_variables (tree vars)
-{
-  tree decl;
-
-  if (warn_unused_variable)
-    for (decl = vars; decl; decl = TREE_CHAIN (decl))
-      if (TREE_CODE (decl) == VAR_DECL
-         && ! TREE_USED (decl)
-         && ! DECL_IN_SYSTEM_HEADER (decl)
-         && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
-       warning ("%Junused variable '%D'", decl, decl);
-}
-
-/* Generate RTL code to terminate a binding contour.
-
-   VARS is the chain of VAR_DECL nodes for the variables bound in this
-   contour.  There may actually be other nodes in this chain, but any
-   nodes other than VAR_DECLS are ignored.
-
-   MARK_ENDS is nonzero if we should put a note at the beginning
-   and end of this binding contour.
-
-   DONT_JUMP_IN is positive if it is not valid to jump into this contour,
-   zero if we can jump into this contour only if it does not have a saved
-   stack level, and negative if we are not to check for invalid use of
-   labels (because the front end does that).  */
-
-void
-expand_end_bindings (tree vars, int mark_ends ATTRIBUTE_UNUSED,
-                    int dont_jump_in ATTRIBUTE_UNUSED)
-{
-  struct nesting *thisblock = block_stack;
-
-  /* If any of the variables in this scope were not used, warn the
-     user.  */
-  warn_about_unused_variables (vars);
-
-  if (thisblock->exit_label)
-    {
-      do_pending_stack_adjust ();
-      emit_label (thisblock->exit_label);
-    }
-
-  /* Mark the beginning and end of the scope if requested.  */
-
-  /* Get rid of the beginning-mark if we don't make an end-mark.  */
-  NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED;
-
-  /* Restore the temporary level of TARGET_EXPRs.  */
-  target_temp_slot_level = thisblock->data.block.block_target_temp_slot_level;
-
-  /* Restore block_stack level for containing block.  */
-
-  POPSTACK (block_stack);
-
-  /* Pop the stack slot nesting and free any slots at this level.  */
-  pop_temp_slots ();
+  /* 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.
@@ -2436,21 +1899,11 @@ expand_decl (tree decl)
 
       /* Note if the object is a user variable.  */
       if (!DECL_ARTIFICIAL (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))));
-       }
-
-      maybe_set_unchanging (DECL_RTL (decl), 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
@@ -2469,9 +1922,8 @@ expand_decl (tree decl)
         to the proper address.  */
       if (DECL_RTL_SET_P (decl))
        {
-         if (!MEM_P (DECL_RTL (decl))
-             || !REG_P (XEXP (DECL_RTL (decl), 0)))
-           abort ();
+         gcc_assert (MEM_P (DECL_RTL (decl)));
+         gcc_assert (REG_P (XEXP (DECL_RTL (decl), 0)));
          oldaddr = XEXP (DECL_RTL (decl), 0);
        }
 
@@ -2502,7 +1954,7 @@ expand_decl (tree decl)
 
       /* Compute the variable's size, in bytes.  This will expand any
         needed SAVE_EXPRs for the first time.  */
-      size = expand_expr (DECL_SIZE_UNIT (decl), NULL_RTX, VOIDmode, 0);
+      size = expand_normal (DECL_SIZE_UNIT (decl));
       free_temp_slots ();
 
       /* Allocate space on the stack for the variable.  Note that
@@ -2528,40 +1980,6 @@ expand_decl (tree decl)
     }
 }
 \f
-/* Emit code to allocate T_SIZE bytes of dynamic stack space for ALLOC.  */
-void
-expand_stack_alloc (tree alloc, tree t_size)
-{
-  rtx address, dest, size;
-  tree var, type;
-
-  if (TREE_CODE (alloc) != ADDR_EXPR)
-    abort ();
-  var = TREE_OPERAND (alloc, 0);
-  if (TREE_CODE (var) != VAR_DECL)
-    abort ();
-
-  type = TREE_TYPE (var);
-
-  /* Compute the variable's size, in bytes.  */
-  size = expand_expr (t_size, NULL_RTX, VOIDmode, 0);
-  free_temp_slots ();
-
-  /* Allocate space on the stack for the variable.  */
-  address = XEXP (DECL_RTL (var), 0);
-  dest = allocate_dynamic_stack_space (size, address, TYPE_ALIGN (type));
-  if (dest != address)
-    emit_move_insn (address, dest);
-
-  /* Indicate the alignment we actually gave this variable.  */
-#ifdef STACK_BOUNDARY
-  DECL_ALIGN (var) = STACK_BOUNDARY;
-#else
-  DECL_ALIGN (var) = BIGGEST_ALIGNMENT;
-#endif
-  DECL_USER_ALIGN (var) = 0;
-}
-
 /* Emit code to save the current value of stack.  */
 rtx
 expand_stack_save (void)
@@ -2577,53 +1995,11 @@ expand_stack_save (void)
 void
 expand_stack_restore (tree var)
 {
-  rtx sa = DECL_RTL (var);
+  rtx sa = expand_normal (var);
 
   emit_stack_restore (SAVE_BLOCK, sa, NULL_RTX);
 }
 \f
-/* Emit code to perform the initialization of a declaration DECL.  */
-
-void
-expand_decl_init (tree decl)
-{
-  int was_used = TREE_USED (decl);
-
-  /* If this is a CONST_DECL, we don't have to generate any code.  Likewise
-     for static decls.  */
-  if (TREE_CODE (decl) == CONST_DECL
-      || TREE_STATIC (decl))
-    return;
-
-  /* Compute and store the initial value now.  */
-
-  push_temp_slots ();
-
-  if (DECL_INITIAL (decl) == error_mark_node)
-    {
-      enum tree_code code = TREE_CODE (TREE_TYPE (decl));
-
-      if (code == INTEGER_TYPE || code == REAL_TYPE || code == ENUMERAL_TYPE
-         || code == POINTER_TYPE || code == REFERENCE_TYPE)
-       expand_assignment (decl, convert (TREE_TYPE (decl), integer_zero_node),
-                          0);
-    }
-  else if (DECL_INITIAL (decl) && TREE_CODE (DECL_INITIAL (decl)) != TREE_LIST)
-    {
-      emit_line_note (DECL_SOURCE_LOCATION (decl));
-      expand_assignment (decl, DECL_INITIAL (decl), 0);
-    }
-
-  /* Don't let the initialization count as "using" the variable.  */
-  TREE_USED (decl) = was_used;
-
-  /* Free any temporaries we made while initializing the decl.  */
-  preserve_temp_slots (NULL_RTX);
-  free_temp_slots ();
-  pop_temp_slots ();
-}
-
-\f
 /* DECL is an anonymous union.  CLEANUP is a cleanup for DECL.
    DECL_ELTS is the list of elements that belong to DECL's type.
    In each, the TREE_VALUE is a VAR_DECL, and the TREE_PURPOSE a cleanup.  */
@@ -2651,6 +2027,7 @@ expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED,
     {
       tree decl_elt = TREE_VALUE (t);
       enum machine_mode mode = TYPE_MODE (TREE_TYPE (decl_elt));
+      rtx decl_rtl;
 
       /* If any of the elements are addressable, so is the entire
         union.  */
@@ -2668,104 +2045,90 @@ expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED,
        DECL_MODE (decl_elt) = mode
          = mode_for_size_tree (DECL_SIZE (decl_elt), MODE_INT, 1);
 
-      /* (SUBREG (MEM ...)) at RTL generation time is invalid, so we
-         instead create a new MEM rtx with the proper mode.  */
-      if (MEM_P (x))
-       {
-         if (mode == GET_MODE (x))
-           SET_DECL_RTL (decl_elt, x);
-         else
-           SET_DECL_RTL (decl_elt, adjust_address_nv (x, mode, 0));
-       }
-      else if (REG_P (x))
+      if (mode == GET_MODE (x))
+       decl_rtl = x;
+      else if (MEM_P (x))
+        /* (SUBREG (MEM ...)) at RTL generation time is invalid, so we
+           instead create a new MEM rtx with the proper mode.  */
+       decl_rtl = adjust_address_nv (x, mode, 0);
+      else
        {
-         if (mode == GET_MODE (x))
-           SET_DECL_RTL (decl_elt, x);
-         else
-           SET_DECL_RTL (decl_elt, gen_lowpart_SUBREG (mode, x));
+         gcc_assert (REG_P (x));
+         decl_rtl = gen_lowpart_SUBREG (mode, x);
        }
-      else
-       abort ();
+      SET_DECL_RTL (decl_elt, decl_rtl);
     }
 }
 \f
-/* Enter a case (Pascal) or switch (C) statement.
-   Push a block onto case_stack and nesting_stack
-   to accumulate the case-labels that are seen
-   and to record the labels generated for the statement.
-
-   EXIT_FLAG is nonzero if `exit_something' should exit this case stmt.
-   Otherwise, this construct is transparent for `exit_something'.
-
-   EXPR is the index-expression to be dispatched on.
-   TYPE is its nominal type.  We could simply convert EXPR to this type,
-   but instead we take short cuts.  */
-
-void
-expand_start_case (tree index_expr)
-{
-  struct nesting *thiscase = ALLOC_NESTING ();
-
-  /* Make an entry on case_stack for the case we are entering.  */
-
-  thiscase->desc = CASE_NESTING;
-  thiscase->next = case_stack;
-  thiscase->all = nesting_stack;
-  thiscase->depth = ++nesting_depth;
-  thiscase->exit_label = 0;
-  thiscase->data.case_stmt.case_list = 0;
-  thiscase->data.case_stmt.index_expr = index_expr;
-  thiscase->data.case_stmt.default_label = 0;
-  case_stack = thiscase;
-  nesting_stack = thiscase;
-
-  do_pending_stack_adjust ();
-
-  /* Make sure case_stmt.start points to something that won't
-     need any transformation before expand_end_case.  */
-  if (!NOTE_P (get_last_insn ()))
-    emit_note (NOTE_INSN_DELETED);
-
-  thiscase->data.case_stmt.start = get_last_insn ();
-}
-
-/* Do the insertion of a case label into
-   case_stack->data.case_stmt.case_list.  The labels are fed to us
-   in descending order from the sorted vector of case labels used
+/* Do the insertion of a case label into case_list.  The labels are
+   fed to us in descending order from the sorted vector of case labels used
    in the tree part of the middle end.  So the list we construct is
-   sorted in ascending order.  */
+   sorted in ascending order.  The bounds on the case range, LOW and HIGH,
+   are converted to case's index type TYPE.  */
 
-void
-add_case_node (tree low, tree high, tree label)
+static struct case_node *
+add_case_node (struct case_node *head, tree type, tree low, tree high,
+               tree label, alloc_pool case_node_pool)
 {
+  tree min_value, max_value;
   struct case_node *r;
 
+  gcc_assert (TREE_CODE (low) == INTEGER_CST);
+  gcc_assert (!high || TREE_CODE (high) == INTEGER_CST);
+
+  min_value = TYPE_MIN_VALUE (type);
+  max_value = TYPE_MAX_VALUE (type);
+
   /* If there's no HIGH value, then this is not a case range; it's
      just a simple case label.  But that's just a degenerate case
      range.
      If the bounds are equal, turn this into the one-value case.  */
   if (!high || tree_int_cst_equal (low, high))
-    high = low;
-
-  /* Handle default labels specially.  */
-  if (!high && !low)
     {
-#ifdef ENABLE_CHECKING
-      if (case_stack->data.case_stmt.default_label != 0)
-       abort ();
-#endif
-      case_stack->data.case_stmt.default_label = label;
-      return;
+      /* If the simple case value is unreachable, ignore it.  */
+      if ((TREE_CODE (min_value) == INTEGER_CST
+            && tree_int_cst_compare (low, min_value) < 0)
+         || (TREE_CODE (max_value) == INTEGER_CST
+             && tree_int_cst_compare (low, max_value) > 0))
+       return head;
+      low = fold_convert (type, low);
+      high = low;
+    }
+  else
+    {
+      /* If the entire case range is unreachable, ignore it.  */
+      if ((TREE_CODE (min_value) == INTEGER_CST
+            && tree_int_cst_compare (high, min_value) < 0)
+         || (TREE_CODE (max_value) == INTEGER_CST
+             && tree_int_cst_compare (low, max_value) > 0))
+       return head;
+
+      /* If the lower bound is less than the index type's minimum
+        value, truncate the range bounds.  */
+      if (TREE_CODE (min_value) == INTEGER_CST
+            && tree_int_cst_compare (low, min_value) < 0)
+       low = min_value;
+      low = fold_convert (type, low);
+
+      /* If the upper bound is greater than the index type's maximum
+        value, truncate the range bounds.  */
+      if (TREE_CODE (max_value) == INTEGER_CST
+         && tree_int_cst_compare (high, max_value) > 0)
+       high = max_value;
+      high = fold_convert (type, high);
     }
 
-  /* Add this label to the chain.  */
-  r = ggc_alloc (sizeof (struct case_node));
-  r->low = low;
-  r->high = high;
+
+  /* Add this label to the chain.  Make sure to drop overflow flags.  */
+  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),
+                               TREE_INT_CST_HIGH (high));
   r->code_label = label;
   r->parent = r->left = NULL;
-  r->right = case_stack->data.case_stmt.case_list;
-  case_stack->data.case_stmt.case_list = r;
+  r->right = head;
+  return r;
 }
 \f
 /* Maximum number of case bit tests.  */
@@ -2773,7 +2136,7 @@ add_case_node (tree low, tree high, tree label)
 
 /* 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
 
@@ -2822,7 +2185,11 @@ case_bit_test_cmp (const void *p1, const void *p2)
   const struct case_bit_test *d1 = p1;
   const struct case_bit_test *d2 = p2;
 
-  return d2->bits - d1->bits;
+  if (d2->bits != d1->bits)
+    return d2->bits - d1->bits;
+
+  /* Stabilize the sort.  */
+  return CODE_LABEL_NUMBER (d2->label) - CODE_LABEL_NUMBER (d1->label);
 }
 
 /*  Expand a switch statement by a short sequence of bit-wise
@@ -2856,15 +2223,14 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
     {
       label = label_rtx (n->code_label);
       for (i = 0; i < count; i++)
-       if (same_case_target_p (label, test[i].label))
+       if (label == test[i].label)
          break;
 
       if (i == count)
        {
-         if (count >= MAX_CASE_BIT_TESTS)
-           abort ();
-          test[i].hi = 0;
-          test[i].lo = 0;
+         gcc_assert (count < MAX_CASE_BIT_TESTS);
+         test[i].hi = 0;
+         test[i].lo = 0;
          test[i].label = label;
          test[i].bits = 1;
          count++;
@@ -2872,10 +2238,10 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
       else
         test[i].bits++;
 
-      lo = tree_low_cst (fold (build (MINUS_EXPR, index_type,
-                                     n->low, minval)), 1);
-      hi = tree_low_cst (fold (build (MINUS_EXPR, index_type,
-                                     n->high, minval)), 1);
+      lo = tree_low_cst (fold_build2 (MINUS_EXPR, index_type,
+                                     n->low, minval), 1);
+      hi = tree_low_cst (fold_build2 (MINUS_EXPR, index_type,
+                                     n->high, minval), 1);
       for (j = lo; j <= hi; j++)
         if (j >= HOST_BITS_PER_WIDE_INT)
          test[i].hi |= (HOST_WIDE_INT) 1 << (j - HOST_BITS_PER_INT);
@@ -2885,14 +2251,14 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
 
   qsort (test, count, sizeof(*test), case_bit_test_cmp);
 
-  index_expr = fold (build (MINUS_EXPR, index_type,
-                           convert (index_type, index_expr),
-                           convert (index_type, minval)));
-  index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
+  index_expr = fold_build2 (MINUS_EXPR, index_type,
+                           fold_convert (index_type, index_expr),
+                           fold_convert (index_type, minval));
+  index = expand_normal (index_expr);
   do_pending_stack_adjust ();
 
   mode = TYPE_MODE (index_type);
-  expr = expand_expr (range, NULL_RTX, VOIDmode, 0);
+  expr = expand_normal (range);
   emit_cmp_and_jump_insns (index, expr, GTU, NULL_RTX, mode, 1,
                           default_label);
 
@@ -2920,18 +2286,18 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
 #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.
    Generate the code to test it and jump to the right place.  */
 
 void
-expand_end_case_type (tree orig_index, tree orig_type)
+expand_case (tree exp)
 {
   tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE;
   rtx default_label = 0;
-  struct case_node *n, *m;
+  struct case_node *n;
   unsigned int count, uniq;
   rtx index;
   rtx table_label;
@@ -2939,61 +2305,79 @@ expand_end_case_type (tree orig_index, tree orig_type)
   rtx *labelvec;
   int i;
   rtx before_case, end, lab;
-  struct nesting *thiscase = case_stack;
-  tree index_expr, index_type;
-  bool exit_done = false;
-  int unsignedp;
 
-  /* Don't crash due to previous errors.  */
-  if (thiscase == NULL)
-    return;
+  tree vec = SWITCH_LABELS (exp);
+  tree orig_type = TREE_TYPE (exp);
+  tree index_expr = SWITCH_COND (exp);
+  tree index_type = TREE_TYPE (index_expr);
+  int unsignedp = TYPE_UNSIGNED (index_type);
 
-  index_expr = thiscase->data.case_stmt.index_expr;
-  index_type = TREE_TYPE (index_expr);
-  unsignedp = TYPE_UNSIGNED (index_type);
-  if (orig_type == NULL)
-    orig_type = TREE_TYPE (orig_index);
+  /* The insn after which the case dispatch should finally
+     be emitted.  Zero for a dummy.  */
+  rtx start;
+
+  /* A list of case labels; it is first built as a list and it may then
+     be rearranged into a nearly balanced binary tree.  */
+  struct case_node *case_list = 0;
+
+  /* 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));
+  gcc_assert (SWITCH_LABELS (exp));
 
   do_pending_stack_adjust ();
 
   /* An ERROR_MARK occurs for various reasons including invalid data type.  */
   if (index_type != error_mark_node)
     {
-      /* If we don't have a default-label, create one here,
-        after the body of the switch.  */
-      if (thiscase->data.case_stmt.default_label == 0)
+      tree elt;
+      bitmap label_bitmap;
+
+      /* cleanup_tree_cfg removes all SWITCH_EXPR with their index
+        expressions being INTEGER_CST.  */
+      gcc_assert (TREE_CODE (index_expr) != INTEGER_CST);
+
+      /* The default case is at the end of TREE_VEC.  */
+      elt = TREE_VEC_ELT (vec, TREE_VEC_LENGTH (vec) - 1);
+      gcc_assert (!CASE_HIGH (elt));
+      gcc_assert (!CASE_LOW (elt));
+      default_label_decl = CASE_LABEL (elt);
+
+      for (i = TREE_VEC_LENGTH (vec) - 1; --i >= 0; )
        {
-         thiscase->data.case_stmt.default_label
-           = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-         /* Share the exit label if possible.  */
-          if (thiscase->exit_label)
-           {
-             SET_DECL_RTL (thiscase->data.case_stmt.default_label,
-                           thiscase->exit_label);
-             exit_done = true;
-           }
-         expand_label (thiscase->data.case_stmt.default_label);
+         tree low, high;
+         elt = TREE_VEC_ELT (vec, i);
+
+         low = CASE_LOW (elt);
+         gcc_assert (low);
+         high = CASE_HIGH (elt);
+
+         /* Discard empty ranges.  */
+         if (high && tree_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 (thiscase->data.case_stmt.default_label);
 
-      before_case = get_last_insn ();
 
-      /* Get upper and lower bounds of case values.
-        Also convert all the case values to the index expr's data type.  */
+      before_case = start = get_last_insn ();
+      default_label = label_rtx (default_label_decl);
+
+      /* Get upper and lower bounds of case values.  */
 
       uniq = 0;
       count = 0;
-      for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
+      label_bitmap = BITMAP_ALLOC (NULL);
+      for (n = case_list; n; n = n->right)
        {
-         /* Check low and high label values are integers.  */
-         if (TREE_CODE (n->low) != INTEGER_CST)
-           abort ();
-         if (TREE_CODE (n->high) != INTEGER_CST)
-           abort ();
-
-         n->low = convert (index_type, n->low);
-         n->high = convert (index_type, n->high);
-
          /* Count the elements and track the largest and smallest
             of them (treating them as signed even if they are not).  */
          if (count++ == 0)
@@ -3003,47 +2387,52 @@ expand_end_case_type (tree orig_index, tree orig_type)
            }
          else
            {
-             if (INT_CST_LT (n->low, minval))
+             if (tree_int_cst_lt (n->low, minval))
                minval = n->low;
-             if (INT_CST_LT (maxval, n->high))
+             if (tree_int_cst_lt (maxval, n->high))
                maxval = n->high;
            }
          /* A range counts double, since it requires two compares.  */
          if (! tree_int_cst_equal (n->low, n->high))
            count++;
 
-         /* Count the number of unique case node targets.  */
-          uniq++;
+         /* If we have not seen this label yet, then increase the
+            number of unique case node targets seen.  */
          lab = label_rtx (n->code_label);
-          for (m = thiscase->data.case_stmt.case_list; m != n; m = m->right)
-            if (same_case_target_p (label_rtx (m->code_label), lab))
-              {
-                uniq--;
-                break;
-              }
+         if (!bitmap_bit_p (label_bitmap, CODE_LABEL_NUMBER (lab)))
+           {
+             bitmap_set_bit (label_bitmap, CODE_LABEL_NUMBER (lab));
+             uniq++;
+           }
        }
 
-      /* Compute span of values.  */
-      if (count != 0)
-       range = fold (build (MINUS_EXPR, index_type, maxval, minval));
+      BITMAP_FREE (label_bitmap);
 
+      /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
+        destination, such as one with a default case only.  However,
+        it doesn't remove cases that are out of range for the switch
+        type, so we may still get a zero here.  */
       if (count == 0)
        {
-         expand_expr (index_expr, const0_rtx, VOIDmode, 0);
          emit_jump (default_label);
+          free_alloc_pool (case_node_pool);
+         return;
        }
 
+      /* Compute span of values.  */
+      range = fold_build2 (MINUS_EXPR, index_type, maxval, minval);
+
       /* Try implementing this switch statement by a short sequence of
         bit-wise comparisons.  However, we let the binary-tree case
         below handle constant index expressions.  */
-      else if (CASE_USE_BIT_TESTS
-              && ! TREE_CONSTANT (index_expr)
-              && compare_tree_int (range, GET_MODE_BITSIZE (word_mode)) < 0
-              && compare_tree_int (range, 0) > 0
-              && lshift_cheap_p ()
-              && ((uniq == 1 && count >= 3)
-                  || (uniq == 2 && count >= 5)
-                  || (uniq == 3 && count >= 6)))
+      if (CASE_USE_BIT_TESTS
+         && ! TREE_CONSTANT (index_expr)
+         && compare_tree_int (range, GET_MODE_BITSIZE (word_mode)) < 0
+         && compare_tree_int (range, 0) > 0
+         && lshift_cheap_p ()
+         && ((uniq == 1 && count >= 3)
+             || (uniq == 2 && count >= 5)
+             || (uniq == 3 && count >= 6)))
        {
          /* Optimize the case where all the case values fit in a
             word without having to subtract MINVAL.  In this case,
@@ -3051,12 +2440,11 @@ expand_end_case_type (tree orig_index, tree orig_type)
          if (compare_tree_int (minval, 0) > 0
              && compare_tree_int (maxval, GET_MODE_BITSIZE (word_mode)) < 0)
            {
-             minval = integer_zero_node;
+             minval = build_int_cst (index_type, 0);
              range = maxval;
            }
          emit_case_bit_tests (index_type, index_expr, minval, range,
-                              thiscase->data.case_stmt.case_list,
-                              default_label);
+                              case_list, default_label);
        }
 
       /* If range of values is much bigger than number of values,
@@ -3073,12 +2461,13 @@ expand_end_case_type (tree orig_index, tree orig_type)
 #ifndef ASM_OUTPUT_ADDR_DIFF_ELT
               || flag_pic
 #endif
+              || !flag_jump_tables
               || TREE_CONSTANT (index_expr)
               /* If neither casesi or tablejump is available, we can
                  only go this way.  */
               || (!HAVE_casesi && !HAVE_tablejump))
        {
-         index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
+         index = expand_normal (index_expr);
 
          /* If the index is a short or char that we do not have
             an insn to handle comparisons directly, convert it to
@@ -3102,58 +2491,26 @@ expand_end_case_type (tree orig_index, tree orig_type)
 
          if (MEM_P (index))
            index = copy_to_reg (index);
-         if (GET_CODE (index) == CONST_INT
-             || TREE_CODE (index_expr) == INTEGER_CST)
-           {
-             /* Make a tree node with the proper constant value
-                if we don't already have one.  */
-             if (TREE_CODE (index_expr) != INTEGER_CST)
-               {
-                 index_expr
-                   = build_int_2 (INTVAL (index),
-                                  unsignedp || INTVAL (index) >= 0 ? 0 : -1);
-                 index_expr = convert (index_type, index_expr);
-               }
 
-             /* For constant index expressions we need only
-                issue an unconditional branch to the appropriate
-                target code.  The job of removing any unreachable
-                code is left to the optimization phase if the
-                "-O" option is specified.  */
-             for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
-               if (! tree_int_cst_lt (index_expr, n->low)
-                   && ! tree_int_cst_lt (n->high, index_expr))
-                 break;
-
-             if (n)
-               emit_jump (label_rtx (n->code_label));
-             else
-               emit_jump (default_label);
-           }
-         else
-           {
-             /* If the index expression is not constant we generate
-                a binary decision tree to select the appropriate
-                target code.  This is done as follows:
-
-                The list of cases is rearranged into a binary tree,
-                nearly optimal assuming equal probability for each case.
-
-                The tree is transformed into RTL, eliminating
-                redundant test conditions at the same time.
-
-                If program flow could reach the end of the
-                decision tree an unconditional jump to the
-                default code is emitted.  */
-
-             use_cost_table
-               = (TREE_CODE (orig_type) != ENUMERAL_TYPE
-                  && estimate_case_costs (thiscase->data.case_stmt.case_list));
-             balance_case_nodes (&thiscase->data.case_stmt.case_list, NULL);
-             emit_case_nodes (index, thiscase->data.case_stmt.case_list,
-                              default_label, index_type);
-             emit_jump (default_label);
-           }
+         /* We generate a binary decision tree to select the
+            appropriate target code.  This is done as follows:
+
+            The list of cases is rearranged into a binary tree,
+            nearly optimal assuming equal probability for each case.
+
+            The tree is transformed into RTL, eliminating
+            redundant test conditions at the same time.
+
+            If program flow could reach the end of the
+            decision tree an unconditional jump to the
+            default code is emitted.  */
+
+         use_cost_table
+           = (TREE_CODE (orig_type) != ENUMERAL_TYPE
+              && estimate_case_costs (case_list));
+         balance_case_nodes (&case_list, NULL);
+         emit_case_nodes (index, case_list, default_label, index_type);
+         emit_jump (default_label);
        }
       else
        {
@@ -3161,7 +2518,7 @@ expand_end_case_type (tree orig_index, tree orig_type)
          if (! try_casesi (index_type, index_expr, minval, range,
                            table_label, default_label))
            {
-             index_type = integer_type_node;
+             bool ok;
 
              /* Index jumptables from zero for suitable values of
                  minval to avoid a subtraction.  */
@@ -3169,13 +2526,13 @@ expand_end_case_type (tree orig_index, tree orig_type)
                  && compare_tree_int (minval, 0) > 0
                  && compare_tree_int (minval, 3) < 0)
                {
-                 minval = integer_zero_node;
+                 minval = build_int_cst (index_type, 0);
                  range = maxval;
                }
 
-             if (! try_tablejump (index_type, index_expr, minval, range,
-                                  table_label, default_label))
-               abort ();
+             ok = try_tablejump (index_type, index_expr, minval, range,
+                                 table_label, default_label);
+             gcc_assert (ok);
            }
 
          /* Get table of labels to jump to, in order of case index.  */
@@ -3184,17 +2541,17 @@ expand_end_case_type (tree orig_index, tree orig_type)
          labelvec = alloca (ncases * sizeof (rtx));
          memset (labelvec, 0, ncases * sizeof (rtx));
 
-         for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
+         for (n = case_list; n; n = n->right)
            {
              /* Compute the low and high bounds relative to the minimum
                 value since that should fit in a HOST_WIDE_INT while the
                 actual values may not.  */
              HOST_WIDE_INT i_low
-               = tree_low_cst (fold (build (MINUS_EXPR, index_type,
-                                            n->low, minval)), 1);
+               = tree_low_cst (fold_build2 (MINUS_EXPR, index_type,
+                                            n->low, minval), 1);
              HOST_WIDE_INT i_high
-               = tree_low_cst (fold (build (MINUS_EXPR, index_type,
-                                            n->high, minval)), 1);
+               = tree_low_cst (fold_build2 (MINUS_EXPR, index_type,
+                                            n->high, minval), 1);
              HOST_WIDE_INT i;
 
              for (i = i_low; i <= i_high; i ++)
@@ -3219,47 +2576,27 @@ expand_end_case_type (tree orig_index, tree orig_type)
            emit_jump_insn (gen_rtx_ADDR_VEC (CASE_VECTOR_MODE,
                                              gen_rtvec_v (ncases, labelvec)));
 
-         /* If the case insn drops through the table,
-            after the table we must jump to the default-label.
-            Otherwise record no drop-through after the table.  */
-#ifdef CASE_DROPS_THROUGH
-         emit_jump (default_label);
-#else
+         /* Record no drop-through after the table.  */
          emit_barrier ();
-#endif
        }
 
       before_case = NEXT_INSN (before_case);
       end = get_last_insn ();
-      if (squeeze_notes (&before_case, &end))
-       abort ();
-      reorder_insns (before_case, end,
-                    thiscase->data.case_stmt.start);
+      reorder_insns (before_case, end, start);
     }
 
-  if (thiscase->exit_label && !exit_done)
-    emit_label (thiscase->exit_label);
-
-  POPSTACK (case_stack);
-
   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
-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
@@ -3289,7 +2626,7 @@ static int
 estimate_case_costs (case_node_ptr node)
 {
   tree min_ascii = integer_minus_one_node;
-  tree max_ascii = convert (TREE_TYPE (node->high), build_int_2 (127, 0));
+  tree max_ascii = build_int_cst (TREE_TYPE (node->high), 127);
   case_node_ptr n;
   int i;
 
@@ -3327,7 +2664,8 @@ estimate_case_costs (case_node_ptr node)
 
   for (n = node; n; n = n->right)
     {
-      if ((INT_CST_LT (n->low, min_ascii)) || INT_CST_LT (max_ascii, n->high))
+      if (tree_int_cst_lt (n->low, min_ascii)
+         || tree_int_cst_lt (max_ascii, n->high))
        return 0;
 
       for (i = (HOST_WIDE_INT) TREE_INT_CST_LOW (n->low);
@@ -3341,16 +2679,6 @@ estimate_case_costs (case_node_ptr node)
   return 1;
 }
 
-/* Determine whether two case labels branch to the same target.
-   Since we now do tree optimizations, just comparing labels is
-   good enough.  */
-
-static bool
-same_case_target_p (rtx l1, rtx l2)
-{
-  return l1 == l2;
-}
-
 /* Take an ordered list of case nodes
    and transform them into a near optimal binary tree,
    on the assumption that any target code selection value is as
@@ -3497,8 +2825,9 @@ node_has_low_bound (case_node_ptr node, tree index_type)
   if (node->left)
     return 0;
 
-  low_minus_one = fold (build (MINUS_EXPR, TREE_TYPE (node->low),
-                              node->low, integer_one_node));
+  low_minus_one = fold_build2 (MINUS_EXPR, TREE_TYPE (node->low),
+                              node->low,
+                              build_int_cst (TREE_TYPE (node->low), 1));
 
   /* If the subtraction above overflowed, we can't verify anything.
      Otherwise, look for a parent that tests our value - 1.  */
@@ -3547,8 +2876,9 @@ node_has_high_bound (case_node_ptr node, tree index_type)
   if (node->right)
     return 0;
 
-  high_plus_one = fold (build (PLUS_EXPR, TREE_TYPE (node->high),
-                              node->high, integer_one_node));
+  high_plus_one = fold_build2 (PLUS_EXPR, TREE_TYPE (node->high),
+                              node->high,
+                              build_int_cst (TREE_TYPE (node->high), 1));
 
   /* If the addition above overflowed, we can't verify anything.
      Otherwise, look for a parent that tests our value + 1.  */
@@ -3609,6 +2939,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);
 
+  /* 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))
@@ -3619,10 +2953,9 @@ 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_expr (node->low, NULL_RTX,
-                                                   VOIDmode, 0),
+                                      expand_normal (node->low),
                                       unsignedp),
                        label_rtx (node->code_label), unsignedp);
 
@@ -3639,8 +2972,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              emit_cmp_and_jump_insns (index,
                                       convert_modes
                                       (mode, imode,
-                                       expand_expr (node->high, NULL_RTX,
-                                                    VOIDmode, 0),
+                                       expand_normal (node->high),
                                        unsignedp),
                                       GT, NULL_RTX, mode, unsignedp,
                                       label_rtx (node->right->code_label));
@@ -3652,8 +2984,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              emit_cmp_and_jump_insns (index,
                                       convert_modes
                                       (mode, imode,
-                                       expand_expr (node->high, NULL_RTX,
-                                                    VOIDmode, 0),
+                                       expand_normal (node->high),
                                        unsignedp),
                                       LT, NULL_RTX, mode, unsignedp,
                                       label_rtx (node->left->code_label));
@@ -3675,22 +3006,18 @@ 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_expr (node->right->low,
-                                                           NULL_RTX,
-                                                           VOIDmode, 0),
+                                              expand_normal (node->right->low),
                                               unsignedp),
                                label_rtx (node->right->code_label),
                                unsignedp);
 
              /* 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_expr (node->left->low,
-                                                           NULL_RTX,
-                                                           VOIDmode, 0),
+                                              expand_normal (node->left->low),
                                               unsignedp),
                                label_rtx (node->left->code_label),
                                unsignedp);
@@ -3707,8 +3034,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              emit_cmp_and_jump_insns (index,
                                       convert_modes
                                       (mode, imode,
-                                       expand_expr (node->high, NULL_RTX,
-                                                    VOIDmode, 0),
+                                       expand_normal (node->high),
                                        unsignedp),
                                       GT, NULL_RTX, mode, unsignedp,
                                       label_rtx (test_label));
@@ -3728,11 +3054,12 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
 
       else if (node->right != 0 && node->left == 0)
        {
-         /* Here we have a right child but no left so we issue conditional
+         /* Here we have a right child but no left so we issue conditional
             branch to default and process the right child.
 
-            Omit the conditional branch to default if we it avoid only one
-            right child; it costs too much space to save so little time.  */
+            Omit the conditional branch to default if the right child
+            does not have any children and is single valued; it would
+            cost too much space to save so little time.  */
 
          if (node->right->right || node->right->left
              || !tree_int_cst_equal (node->right->low, node->right->high))
@@ -3742,8 +3069,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
                  emit_cmp_and_jump_insns (index,
                                           convert_modes
                                           (mode, imode,
-                                           expand_expr (node->high, NULL_RTX,
-                                                        VOIDmode, 0),
+                                           expand_normal (node->high),
                                            unsignedp),
                                           LT, NULL_RTX, mode, unsignedp,
                                           default_label);
@@ -3755,11 +3081,10 @@ 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_expr (node->right->low, NULL_RTX,
-                                           VOIDmode, 0),
+                              expand_normal (node->right->low),
                               unsignedp),
                              label_rtx (node->right->code_label), unsignedp);
        }
@@ -3775,8 +3100,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
                  emit_cmp_and_jump_insns (index,
                                           convert_modes
                                           (mode, imode,
-                                           expand_expr (node->high, NULL_RTX,
-                                                        VOIDmode, 0),
+                                           expand_normal (node->high),
                                            unsignedp),
                                           GT, NULL_RTX, mode, unsignedp,
                                           default_label);
@@ -3788,11 +3112,10 @@ 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_expr (node->left->low, NULL_RTX,
-                                           VOIDmode, 0),
+                              expand_normal (node->left->low),
                               unsignedp),
                              label_rtx (node->left->code_label), unsignedp);
        }
@@ -3818,8 +3141,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
            emit_cmp_and_jump_insns (index,
                                     convert_modes
                                     (mode, imode,
-                                     expand_expr (node->high, NULL_RTX,
-                                                  VOIDmode, 0),
+                                     expand_normal (node->high),
                                      unsignedp),
                                     GT, NULL_RTX, mode, unsignedp,
                                     label_rtx (node->right->code_label));
@@ -3832,8 +3154,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              emit_cmp_and_jump_insns (index,
                                       convert_modes
                                       (mode, imode,
-                                       expand_expr (node->high, NULL_RTX,
-                                                    VOIDmode, 0),
+                                       expand_normal (node->high),
                                        unsignedp),
                                       GT, NULL_RTX, mode, unsignedp,
                                       label_rtx (test_label));
@@ -3844,8 +3165,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
          emit_cmp_and_jump_insns (index,
                                   convert_modes
                                   (mode, imode,
-                                   expand_expr (node->low, NULL_RTX,
-                                                VOIDmode, 0),
+                                   expand_normal (node->low),
                                    unsignedp),
                                   GE, NULL_RTX, mode, unsignedp,
                                   label_rtx (node->code_label));
@@ -3875,8 +3195,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              emit_cmp_and_jump_insns (index,
                                       convert_modes
                                       (mode, imode,
-                                       expand_expr (node->low, NULL_RTX,
-                                                    VOIDmode, 0),
+                                       expand_normal (node->low),
                                        unsignedp),
                                       LT, NULL_RTX, mode, unsignedp,
                                       default_label);
@@ -3887,8 +3206,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
          emit_cmp_and_jump_insns (index,
                                   convert_modes
                                   (mode, imode,
-                                   expand_expr (node->high, NULL_RTX,
-                                                VOIDmode, 0),
+                                   expand_normal (node->high),
                                    unsignedp),
                                   LE, NULL_RTX, mode, unsignedp,
                                   label_rtx (node->code_label));
@@ -3905,8 +3223,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              emit_cmp_and_jump_insns (index,
                                       convert_modes
                                       (mode, imode,
-                                       expand_expr (node->high, NULL_RTX,
-                                                    VOIDmode, 0),
+                                       expand_normal (node->high),
                                        unsignedp),
                                       GT, NULL_RTX, mode, unsignedp,
                                       default_label);
@@ -3917,8 +3234,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
          emit_cmp_and_jump_insns (index,
                                   convert_modes
                                   (mode, imode,
-                                   expand_expr (node->low, NULL_RTX,
-                                                VOIDmode, 0),
+                                   expand_normal (node->low),
                                    unsignedp),
                                   GE, NULL_RTX, mode, unsignedp,
                                   label_rtx (node->code_label));
@@ -3939,8 +3255,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              emit_cmp_and_jump_insns (index,
                                       convert_modes
                                       (mode, imode,
-                                       expand_expr (node->high, NULL_RTX,
-                                                    VOIDmode, 0),
+                                       expand_normal (node->high),
                                        unsignedp),
                                       GT, NULL_RTX, mode, unsignedp,
                                       default_label);
@@ -3951,8 +3266,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              emit_cmp_and_jump_insns (index,
                                       convert_modes
                                       (mode, imode,
-                                       expand_expr (node->low, NULL_RTX,
-                                                    VOIDmode, 0),
+                                       expand_normal (node->low),
                                        unsignedp),
                                       LT, NULL_RTX, mode, unsignedp,
                                       default_label);
@@ -3967,13 +3281,13 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
 
              /* Instead of doing two branches, emit one unsigned branch for
                 (index-low) > (high-low).  */
-             low_rtx = expand_expr (low, NULL_RTX, mode, 0);
+             low_rtx = expand_expr (low, NULL_RTX, mode, EXPAND_NORMAL);
              new_index = expand_simple_binop (mode, MINUS, index, low_rtx,
                                               NULL_RTX, unsignedp,
                                               OPTAB_WIDEN);
-             new_bound = expand_expr (fold (build (MINUS_EXPR, type,
-                                                   high, low)),
-                                      NULL_RTX, mode, 0);
+             new_bound = expand_expr (fold_build2 (MINUS_EXPR, type,
+                                                   high, low),
+                                      NULL_RTX, mode, EXPAND_NORMAL);
 
              emit_cmp_and_jump_insns (new_index, new_bound, GT, NULL_RTX,
                                       mode, 1, default_label);
@@ -3983,5 +3297,3 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
        }
     }
 }
-
-#include "gt-stmt.h"