]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/stmt.c
(digest_init): Use TYPE_MAIN_VARIANT comparing type of inside_init.
[gcc.git] / gcc / stmt.c
index 744666454a47762e0b70c02ea308bd4ebd568f6e..eb24d39b57bbf0182716fdd37284545b3fcef68c 100644 (file)
@@ -54,9 +54,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define obstack_chunk_free free
 struct obstack stmt_obstack;
 
-extern int xmalloc ();
-extern void free ();
-
 /* Filename and line number of last line-number note,
    whether we actually emitted it or not.  */
 char *emit_filename;
@@ -534,10 +531,9 @@ void
 expand_computed_goto (exp)
      tree exp;
 {
-  rtx x = expand_expr (exp, 0, VOIDmode, 0);
+  rtx x = expand_expr (exp, NULL_RTX, VOIDmode, 0);
   emit_queue ();
   emit_indirect_jump (x);
-  emit_barrier ();
 }
 \f
 /* Handle goto statements and the labels that they can go to.  */
@@ -586,11 +582,9 @@ declare_nonlocal_label (label)
     {
       nonlocal_goto_handler_slot
        = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
-      nonlocal_goto_stack_level
-       = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
-      emit_insn_before (gen_move_insn (nonlocal_goto_stack_level,
-                                      stack_pointer_rtx),
-                       tail_recursion_reentry);
+      emit_stack_save (SAVE_NONLOCAL,
+                      &nonlocal_goto_stack_level,
+                      PREV_INSN (tail_recursion_reentry));
     }
 }
 
@@ -609,27 +603,49 @@ expand_goto (label)
       struct function *p = find_function_data (context);
       rtx temp;
       p->has_nonlocal_label = 1;
+
+      /* Copy the rtl for the slots so that they won't be shared in
+        case the virtual stack vars register gets instantiated differently
+        in the parent than in the child.  */
+
 #if HAVE_nonlocal_goto
       if (HAVE_nonlocal_goto)
        emit_insn (gen_nonlocal_goto (lookup_static_chain (label),
-                                     p->nonlocal_goto_handler_slot,
-                                     p->nonlocal_goto_stack_level,
+                                     copy_rtx (p->nonlocal_goto_handler_slot),
+                                     copy_rtx (p->nonlocal_goto_stack_level),
                                      gen_rtx (LABEL_REF, Pmode,
                                               label_rtx (label))));
       else
 #endif
        {
+         rtx addr;
+
          /* Restore frame pointer for containing function.
             This sets the actual hard register used for the frame pointer
             to the location of the function's incoming static chain info.
             The non-local goto handler will then adjust it to contain the
             proper value and reload the argument pointer, if needed.  */
          emit_move_insn (frame_pointer_rtx, lookup_static_chain (label));
+
+         /* We have now loaded the frame pointer hardware register with
+            the address of that corresponds to the start of the virtual
+            stack vars.  So replace virtual_stack_vars_rtx in all
+            addresses we use with stack_pointer_rtx.  */
+
          /* Get addr of containing function's current nonlocal goto handler,
             which will do any cleanups and then jump to the label.  */
-         temp = copy_to_reg (p->nonlocal_goto_handler_slot);
+         addr = copy_rtx (p->nonlocal_goto_handler_slot);
+         temp = copy_to_reg (replace_rtx (addr, virtual_stack_vars_rtx,
+                                          frame_pointer_rtx));
+         
          /* Restore the stack pointer.  Note this uses fp just restored.  */
-         emit_move_insn (stack_pointer_rtx, p->nonlocal_goto_stack_level);
+         addr = p->nonlocal_goto_stack_level;
+         if (addr)
+           addr = replace_rtx (copy_rtx (addr),
+                               virtual_stack_vars_rtx, frame_pointer_rtx);
+
+         emit_stack_restore (SAVE_NONLOCAL, addr, NULL_RTX);
+
          /* Put in the static chain register the nonlocal label address.  */
          emit_move_insn (static_chain_rtx,
                          gen_rtx (LABEL_REF, Pmode, label_rtx (label)));
@@ -642,7 +658,7 @@ expand_goto (label)
        }
      }
   else
-    expand_goto_internal (label, label_rtx (label), 0);
+    expand_goto_internal (label, label_rtx (label), NULL_RTX);
 }
 
 /* Generate RTL code for a `goto' statement with target label BODY.
@@ -680,7 +696,7 @@ expand_goto_internal (body, label, last_insn)
          /* Execute the cleanups for blocks we are exiting.  */
          if (block->data.block.cleanups != 0)
            {
-             expand_cleanups (block->data.block.cleanups, 0);
+             expand_cleanups (block->data.block.cleanups, NULL_TREE);
              do_pending_stack_adjust ();
            }
        }
@@ -691,7 +707,7 @@ expand_goto_internal (body, label, last_insn)
             the stack pointer.  This one should be deleted as dead by flow. */
          clear_pending_stack_adjust ();
          do_pending_stack_adjust ();
-         emit_move_insn (stack_pointer_rtx, stack_level);
+         emit_stack_restore (SAVE_BLOCK, stack_level, NULL_RTX);
        }
 
       if (body != 0 && DECL_TOO_LATE (body))
@@ -808,7 +824,7 @@ expand_fixup (tree_label, rtl_label, last_insn)
 #endif
             )
            || block->data.block.cleanups)
-          ? tree_cons (0, block->data.block.cleanups,
+          ? tree_cons (NULL_TREE, block->data.block.cleanups,
                        block->data.block.outer_cleanups)
           : 0);
       fixup->next = goto_fixup_chain;
@@ -879,12 +895,12 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
              && (after_label == 0
                  || INSN_UID (first_insn) < INSN_UID (after_label))
              && INSN_UID (first_insn) > INSN_UID (f->before_jump)
-             && ! TREE_REGDECL (f->target))
+             && ! DECL_REGISTER (f->target))
            {
              error_with_decl (f->target,
                               "label `%s' used before containing binding contour");
              /* Prevent multiple errors for one label.  */
-             TREE_REGDECL (f->target) = 1;
+             DECL_REGISTER (f->target) = 1;
            }
 
          /* Execute cleanups for blocks this jump exits.  */
@@ -902,8 +918,7 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
          /* Restore stack level for the biggest contour that this
             jump jumps out of.  */
          if (f->stack_level)
-           emit_insn_after (gen_move_insn (stack_pointer_rtx, f->stack_level),
-                            f->before_jump);
+           emit_stack_restore (SAVE_BLOCK, f->stack_level, f->before_jump);
          f->before_jump = 0;
        }
     }
@@ -980,7 +995,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
   rtx body;
   int ninputs = list_length (inputs);
   int noutputs = list_length (outputs);
-  int nclobbers = list_length (clobbers);
+  int nclobbers;
   tree tail;
   register int i;
   /* Vector of RTX's of evaluated output operands.  */
@@ -988,6 +1003,17 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
   /* The insn we have emitted.  */
   rtx insn;
 
+  /* Count the number of meaningful clobbered registers, ignoring what
+     we would ignore later.  */
+  nclobbers = 0;
+  for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
+    {
+      char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
+      i = decode_reg_name (regname);
+      if (i >= 0 || i == -4)
+       ++nclobbers;
+    }
+
   last_expr_type = 0;
 
   for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
@@ -1036,7 +1062,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
          && TREE_CODE (val) != INDIRECT_REF)
        TREE_VALUE (tail) = save_expr (TREE_VALUE (tail));
 
-      output_rtx[i] = expand_expr (TREE_VALUE (tail), 0, VOIDmode, 0);
+      output_rtx[i] = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
     }
 
   if (ninputs + noutputs > MAX_RECOG_OPERANDS)
@@ -1087,7 +1113,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
          }
 
       XVECEXP (body, 3, i)      /* argvec */
-       = expand_expr (TREE_VALUE (tail), 0, VOIDmode, 0);
+       = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
       XVECEXP (body, 4, i)      /* constraints */
        = gen_rtx (ASM_INPUT, TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
                   TREE_STRING_POINTER (TREE_PURPOSE (tail)));
@@ -1148,19 +1174,28 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
 
       /* Store (clobber REG) for each clobbered register specified.  */
 
-      for (tail = clobbers; tail; tail = TREE_CHAIN (tail), i++)
+      for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
        {
          char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
          int j = decode_reg_name (regname);
 
          if (j < 0)
            {
+             if (j == -3)      /* `cc', which is not a register */
+               continue;
+
+             if (j == -4)      /* `memory', don't cache memory across asm */
+               {
+                 XVECEXP (body, 0, i++) = gen_rtx (CLOBBER, VOIDmode, const0_rtx);
+                 continue;
+               }
+
              error ("unknown register name `%s' in `asm'", regname);
              return;
            }
 
          /* Use QImode since that's guaranteed to clobber just one reg.  */
-         XVECEXP (body, 0, i)
+         XVECEXP (body, 0, i++)
            = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, QImode, j));
        }
 
@@ -1192,7 +1227,9 @@ expand_expr_stmt (exp)
     }
   last_expr_type = TREE_TYPE (exp);
   if (! flag_syntax_only)
-    last_expr_value = expand_expr (exp, expr_stmts_for_value ? 0 : const0_rtx,
+    last_expr_value = expand_expr (exp,
+                                  (expr_stmts_for_value
+                                   ? NULL_RTX : const0_rtx),
                                   VOIDmode, 0);
 
   /* If all we do is reference a volatile value in memory,
@@ -1203,8 +1240,18 @@ expand_expr_stmt (exp)
       if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
        copy_to_reg (last_expr_value);
       else
-       /* This case needs to be written.  */
-       abort ();
+       {
+         rtx lab = gen_label_rtx ();
+         
+         /* Compare the value with itself to reference it.  */
+         emit_cmp_insn (last_expr_value, last_expr_value, EQ,
+                        expand_expr (TYPE_SIZE (last_expr_type),
+                                     NULL_RTX, VOIDmode, 0),
+                        BLKmode, 0,
+                        TYPE_ALIGN (last_expr_type) / BITS_PER_UNIT);
+         emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (lab));
+         emit_label (lab);
+       }
     }
 
   /* If this expression is part of a ({...}) and is in memory, we may have
@@ -1262,6 +1309,9 @@ warn_if_unused_value (exp)
     case COMPOUND_EXPR:
       if (warn_if_unused_value (TREE_OPERAND (exp, 0)))
        return 1;
+      /* Let people do `(foo (), 0)' without a warning.  */
+      if (TREE_CONSTANT (TREE_OPERAND (exp, 1)))
+       return 0;
       return warn_if_unused_value (TREE_OPERAND (exp, 1));
 
     case NOP_EXPR:
@@ -1285,6 +1335,11 @@ warn_if_unused_value (exp)
        return 0;
 
     default:
+      /* Referencing a volatile value is a side effect, so don't warn.  */
+      if ((TREE_CODE_CLASS (TREE_CODE (exp)) == 'd'
+          || TREE_CODE_CLASS (TREE_CODE (exp)) == 'r')
+         && TREE_THIS_VOLATILE (exp))
+       return 0;
       warning_with_file_and_line (emit_filename, emit_lineno,
                                  "value computed is not used");
       return 1;
@@ -1388,6 +1443,7 @@ expand_end_stmt_expr (t)
        }
 
     }
+*/
 
 /* Return nonzero iff in a try block at level LEVEL.  */
 
@@ -1486,7 +1542,7 @@ expand_start_try (try_clause, exitflag, escapeflag)
   except_stack = thishandler;
   nesting_stack = thishandler;
 
-  do_jump (try_clause, thishandler->data.except_stmt.except_label, NULL);
+  do_jump (try_clause, thishandler->data.except_stmt.except_label, NULL_RTX);
 }
 
 /* End of a TRY block.  Nothing to do for now.  */
@@ -1495,7 +1551,8 @@ void
 expand_end_try ()
 {
   except_stack->data.except_stmt.after_label = gen_label_rtx ();
-  expand_goto_internal (NULL, except_stack->data.except_stmt.after_label, 0);
+  expand_goto_internal (NULL_TREE, except_stack->data.except_stmt.after_label,
+                       NULL_RTX);
 }
 
 /* Start an `except' nesting contour.
@@ -1558,7 +1615,8 @@ expand_escape_except ()
   for (n = except_stack; n; n = n->next)
     if (n->data.except_stmt.escape_label != 0)
       {
-       expand_goto_internal (0, n->data.except_stmt.escape_label, 0);
+       expand_goto_internal (NULL_TREE,
+                             n->data.except_stmt.escape_label, NULL_RTX);
        return 1;
       }
 
@@ -1661,7 +1719,8 @@ expand_end_catch ()
 {
   if (except_stack == 0 || except_stack->data.except_stmt.after_label == 0)
     return 0;
-  expand_goto_internal (0, except_stack->data.except_stmt.after_label, 0);
+  expand_goto_internal (NULL_TREE, except_stack->data.except_stmt.after_label,
+                       NULL_RTX);
   return 1;
 }
 \f
@@ -1692,7 +1751,7 @@ expand_start_cond (cond, exitflag)
   cond_stack = thiscond;
   nesting_stack = thiscond;
 
-  do_jump (cond, thiscond->data.cond.next_label, NULL);
+  do_jump (cond, thiscond->data.cond.next_label, NULL_RTX);
 }
 
 /* Generate RTL between then-clause and the elseif-clause
@@ -1707,7 +1766,7 @@ expand_start_elseif (cond)
   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);
+  do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX);
 }
 
 /* Generate RTL between the then-clause and the else-clause
@@ -1768,7 +1827,7 @@ expand_start_loop (exit_flag)
 
   do_pending_stack_adjust ();
   emit_queue ();
-  emit_note (0, NOTE_INSN_LOOP_BEG);
+  emit_note (NULL_PTR, NOTE_INSN_LOOP_BEG);
   emit_label (thisloop->data.loop.start_label);
 
   return thisloop;
@@ -1795,7 +1854,7 @@ void
 expand_loop_continue_here ()
 {
   do_pending_stack_adjust ();
-  emit_note (0, NOTE_INSN_LOOP_CONT);
+  emit_note (NULL_PTR, NOTE_INSN_LOOP_CONT);
   emit_label (loop_stack->data.loop.continue_label);
 }
 
@@ -1899,7 +1958,7 @@ expand_end_loop ()
     }
 
   emit_jump (start_label);
-  emit_note (0, NOTE_INSN_LOOP_END);
+  emit_note (NULL_PTR, NOTE_INSN_LOOP_END);
   emit_label (loop_stack->data.loop.end_label);
 
   POPSTACK (loop_stack);
@@ -1921,7 +1980,8 @@ expand_continue_loop (whichloop)
     whichloop = loop_stack;
   if (whichloop == 0)
     return 0;
-  expand_goto_internal (0, whichloop->data.loop.continue_label, 0);
+  expand_goto_internal (NULL_TREE, whichloop->data.loop.continue_label,
+                       NULL_RTX);
   return 1;
 }
 
@@ -1937,7 +1997,7 @@ expand_exit_loop (whichloop)
     whichloop = loop_stack;
   if (whichloop == 0)
     return 0;
-  expand_goto_internal (0, whichloop->data.loop.end_label, 0);
+  expand_goto_internal (NULL_TREE, whichloop->data.loop.end_label, NULL_RTX);
   return 1;
 }
 
@@ -1955,7 +2015,7 @@ expand_exit_loop_if_false (whichloop, cond)
     whichloop = loop_stack;
   if (whichloop == 0)
     return 0;
-  do_jump (cond, whichloop->data.loop.end_label, NULL);
+  do_jump (cond, whichloop->data.loop.end_label, NULL_RTX);
   return 1;
 }
 
@@ -2002,7 +2062,7 @@ expand_exit_something ()
   for (n = nesting_stack; n; n = n->all)
     if (n->exit_label != 0)
       {
-       expand_goto_internal (0, n->exit_label, 0);
+       expand_goto_internal (NULL_TREE, n->exit_label, NULL_RTX);
        return 1;
       }
 
@@ -2080,7 +2140,7 @@ expand_null_return_1 (last_insn, use_goto)
     {
       if (end_label == 0)
        end_label = return_label = gen_label_rtx ();
-      expand_goto_internal (0, end_label, last_insn);
+      expand_goto_internal (NULL_TREE, end_label, last_insn);
       return;
     }
 
@@ -2096,7 +2156,7 @@ expand_null_return_1 (last_insn, use_goto)
 #endif
 
   /* Otherwise jump to the epilogue.  */
-  expand_goto_internal (0, end_label, last_insn);
+  expand_goto_internal (NULL_TREE, end_label, last_insn);
 }
 \f
 /* Generate RTL to evaluate the expression RETVAL and return it
@@ -2124,7 +2184,7 @@ expand_return (retval)
   /* If function wants no value, give it none.  */
   if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE)
     {
-      expand_expr (retval, 0, VOIDmode, 0);
+      expand_expr (retval, NULL_RTX, VOIDmode, 0);
       expand_null_return ();
       return;
     }
@@ -2160,7 +2220,7 @@ expand_return (retval)
          || TREE_CODE (TREE_OPERAND (retval_rhs, 2)) == CALL_EXPR))
     {
       rtx label = gen_label_rtx ();
-      do_jump (TREE_OPERAND (retval_rhs, 0), label, 0);
+      do_jump (TREE_OPERAND (retval_rhs, 0), label, NULL_RTX);
       expand_return (build (MODIFY_EXPR, TREE_TYPE (current_function_decl),
                            DECL_RESULT (current_function_decl),
                            TREE_OPERAND (retval_rhs, 1)));
@@ -2192,7 +2252,8 @@ expand_return (retval)
          emit_label_after (tail_recursion_label,
                            tail_recursion_reentry);
        }
-      expand_goto_internal (0, tail_recursion_label, last_insn);
+      emit_queue ();
+      expand_goto_internal (NULL_TREE, tail_recursion_label, last_insn);
       emit_barrier ();
       return;
     }
@@ -2238,7 +2299,7 @@ expand_return (retval)
       && GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == REG)
     {
       /* Calculate the return value into a pseudo reg.  */
-      val = expand_expr (retval_rhs, 0, VOIDmode, 0);
+      val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
       emit_queue ();
       /* All temporaries have now been used.  */
       free_temp_slots ();
@@ -2249,7 +2310,7 @@ expand_return (retval)
     {
       /* No cleanups or no hard reg used;
         calculate value into hard return reg.  */
-      expand_expr (retval, 0, VOIDmode, 0);
+      expand_expr (retval, NULL_RTX, VOIDmode, 0);
       emit_queue ();
       free_temp_slots ();
       expand_value_return (DECL_RTL (DECL_RESULT (current_function_decl)));
@@ -2304,7 +2365,7 @@ tail_recursion_args (actuals, formals)
   argvec = (rtx *) alloca (i * sizeof (rtx));
 
   for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++)
-    argvec[i] = expand_expr (TREE_VALUE (a), 0, VOIDmode, 0);
+    argvec[i] = expand_expr (TREE_VALUE (a), NULL_RTX, VOIDmode, 0);
 
   /* Find which actual values refer to current values of previous formals.
      Copy each of them now, before any formal is changed.  */
@@ -2348,7 +2409,7 @@ expand_start_bindings (exit_flag)
 {
   struct nesting *thisblock = ALLOC_NESTING ();
 
-  rtx note = emit_note (0, NOTE_INSN_BLOCK_BEG);
+  rtx note = emit_note (NULL_PTR, NOTE_INSN_BLOCK_BEG);
 
   /* Make an entry on block_stack for the block we are entering.  */
 
@@ -2421,7 +2482,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
   /* Mark the beginning and end of the scope if requested.  */
 
   if (mark_ends)
-    emit_note (0, NOTE_INSN_BLOCK_END);
+    emit_note (NULL_PTR, NOTE_INSN_BLOCK_END);
   else
     /* 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;
@@ -2489,16 +2550,35 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
 #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
       if (fixed_regs[ARG_POINTER_REGNUM])
        {
-         /* Now restore our arg pointer from the address at which it was saved
-            in our stack frame.
-            If there hasn't be space allocated for it yet, make some now.  */
-         if (arg_pointer_save_area == 0)
-           arg_pointer_save_area
-             = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
-         emit_move_insn (virtual_incoming_args_rtx,
-                         /* We need a pseudo here,
-                            or else instantiate_virtual_regs_1 complains.  */
-                         copy_to_reg (arg_pointer_save_area));
+#ifdef ELIMINABLE_REGS
+         /* If the argument pointer can be eliminated in favor of the
+            frame pointer, we don't need to restore it.  We assume here
+            that if such an elimination is present, it can always be used.
+            This is the case on all known machines; if we don't make this
+            assumption, we do unnecessary saving on many machines.  */
+         static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
+         int i;
+
+         for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
+           if (elim_regs[i].from == ARG_POINTER_REGNUM
+               && elim_regs[i].to == FRAME_POINTER_REGNUM)
+             break;
+
+         if (i == sizeof elim_regs / sizeof elim_regs [0])
+#endif
+           {
+             /* Now restore our arg pointer from the address at which it
+                was saved in our stack frame.
+                If there hasn't be space allocated for it yet, make
+                some now.  */
+             if (arg_pointer_save_area == 0)
+               arg_pointer_save_area
+                 = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
+             emit_move_insn (virtual_incoming_args_rtx,
+                             /* We need a pseudo here, or else
+                                instantiate_virtual_regs_1 complains.  */
+                             copy_to_reg (arg_pointer_save_area));
+           }
        }
 #endif
 
@@ -2560,7 +2640,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
       expr_stmts_for_value = 0;
 
       /* Do the cleanups.  */
-      expand_cleanups (thisblock->data.block.cleanups, 0);
+      expand_cleanups (thisblock->data.block.cleanups, NULL_TREE);
       do_pending_stack_adjust ();
 
       expr_stmts_for_value = old_expr_stmts_for_value;
@@ -2571,14 +2651,16 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
 
       if (thisblock->data.block.stack_level != 0)
        {
-         emit_move_insn (stack_pointer_rtx,
-                         thisblock->data.block.stack_level);
-         if (nonlocal_goto_stack_level != 0)
-           emit_move_insn (nonlocal_goto_stack_level, stack_pointer_rtx);
+         emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
+                             thisblock->data.block.stack_level, NULL_RTX);
+         if (nonlocal_goto_handler_slot != 0)
+           emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level,
+                            NULL_RTX);
        }
 
       /* Any gotos out of this block must also do these things.
-        Also report any gotos with fixups that came to labels in this level.  */
+        Also report any gotos with fixups that came to labels in this
+        level.  */
       fixup_gotos (thisblock,
                   thisblock->data.block.stack_level,
                   thisblock->data.block.cleanups,
@@ -2639,7 +2721,7 @@ expand_decl (decl)
 
   if (TREE_CODE (decl) != VAR_DECL)
     return;
-  if (TREE_STATIC (decl) || TREE_EXTERNAL (decl))
+  if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
     return;
 
   /* Create the RTL representation for the variable.  */
@@ -2664,7 +2746,7 @@ expand_decl (decl)
                && TREE_CODE (type) == REAL_TYPE)
           && ! TREE_THIS_VOLATILE (decl)
           && ! TREE_ADDRESSABLE (decl)
-          && (TREE_REGDECL (decl) || ! obey_regdecls))
+          && (DECL_REGISTER (decl) || ! obey_regdecls))
     {
       /* Automatic variable that can go in a register.  */
       DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
@@ -2732,8 +2814,9 @@ expand_decl (decl)
       if (thisblock->data.block.stack_level == 0)
        {
          do_pending_stack_adjust ();
-         thisblock->data.block.stack_level
-           = copy_to_reg (stack_pointer_rtx);
+         emit_stack_save (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
+                          &thisblock->data.block.stack_level,
+                          thisblock->data.block.first_insn);
          stack_block_stack = thisblock;
        }
 
@@ -2741,18 +2824,29 @@ expand_decl (decl)
       size = expand_expr (size_binop (CEIL_DIV_EXPR,
                                      DECL_SIZE (decl),
                                      size_int (BITS_PER_UNIT)),
-                         0, VOIDmode, 0);
+                         NULL_RTX, VOIDmode, 0);
       free_temp_slots ();
 
+      /* This is equivalent to calling alloca.  */
+      current_function_calls_alloca = 1;
+
       /* Allocate space on the stack for the variable.  */
-      address = allocate_dynamic_stack_space (size, 0);
+      address = allocate_dynamic_stack_space (size, NULL_RTX,
+                                             DECL_ALIGN (decl));
 
-      if (nonlocal_goto_stack_level != 0)
-       emit_move_insn (nonlocal_goto_stack_level, stack_pointer_rtx);
+      if (nonlocal_goto_handler_slot != 0)
+       emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
 
       /* Reference the variable indirect through that rtx.  */
       DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), address);
 
+      /* If this is a memory ref that contains aggregate components,
+        mark it as such for cse and loop optimize.  */
+      MEM_IN_STRUCT_P (DECL_RTL (decl))
+       = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+          || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+          || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE);
+
       /* Indicate the alignment we actually gave this variable.  */
 #ifdef STACK_BOUNDARY
       DECL_ALIGN (decl) = STACK_BOUNDARY;
@@ -2945,7 +3039,7 @@ fixup_cleanups (list, before_jump)
   rtx beyond_jump = get_last_insn ();
   rtx new_before_jump;
 
-  expand_cleanups (list, 0);
+  expand_cleanups (list, NULL_TREE);
   /* Pop any pushes done in the cleanups,
      in case function is about to return.  */
   do_pending_stack_adjust ();
@@ -3059,7 +3153,7 @@ expand_start_case (exit_flag, expr, type, printname)
   /* Make sure case_stmt.start points to something that won't
      need any transformation before expand_end_case.  */
   if (GET_CODE (get_last_insn ()) != NOTE)
-    emit_note (0, NOTE_INSN_DELETED);
+    emit_note (NULL_PTR, NOTE_INSN_DELETED);
 
   thiscase->data.case_stmt.start = get_last_insn ();
 }
@@ -3376,10 +3470,10 @@ check_for_full_enumeration_handling (type)
           n = n->right)
        ;
 
-      if (!(n && tree_int_cst_equal (n->low, TREE_VALUE (chain))))
+      if (!n || tree_int_cst_lt (TREE_VALUE (chain), n->low))
        {
          if (warn_switch)
-           warning ("enumerated value `%s' not handled in switch",
+           warning ("enumeration value `%s' not handled in switch",
                     IDENTIFIER_POINTER (TREE_PURPOSE (chain)));
          all_values = 0;
        }
@@ -3405,6 +3499,21 @@ check_for_full_enumeration_handling (type)
                                        == IDENTIFIER_NODE)
                                       ? TYPE_NAME (type)
                                       : DECL_NAME (TYPE_NAME (type))));
+       if (!tree_int_cst_equal (n->low, n->high))
+         {
+           for (chain = TYPE_VALUES (type);
+                chain && !tree_int_cst_equal (n->high, TREE_VALUE (chain));
+                chain = TREE_CHAIN (chain))
+             ;
+
+           if (!chain)
+             warning ("case value `%d' not in enumerated type `%s'",
+                      TREE_INT_CST_LOW (n->high),
+                      IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
+                                           == IDENTIFIER_NODE)
+                                          ? TYPE_NAME (type)
+                                          : DECL_NAME (TYPE_NAME (type))));
+         }
       }
 
   /* If all values were found as case labels, make one of them the default
@@ -3425,7 +3534,7 @@ check_for_full_enumeration_handling (type)
 }
 \f
 /* Terminate a case (Pascal) or switch (C) statement
-   in which CASE_INDEX is the expression to be tested.
+   in which ORIG_INDEX is the expression to be tested.
    Generate the code to test it and jump to the right place.  */
 
 void
@@ -3540,16 +3649,22 @@ expand_end_case (orig_index)
         make a sequence of conditional branches instead of a dispatch.
         If the switch-index is a constant, do it this way
         because we can optimize it.  */
-      else if (TREE_INT_CST_HIGH (range) != 0
+
+#ifndef CASE_VALUES_THRESHOLD
 #ifdef HAVE_casesi
-              || (HAVE_casesi ? count < 4 : count < 5)
+#define CASE_VALUES_THRESHOLD (HAVE_casesi ? 4 : 5)
 #else
-              /* If machine does not have a case insn that compares the
-                 bounds, this means extra overhead for dispatch tables
-                 which raises the threshold for using them.  */
-              || count < 5
-#endif
-              || (unsigned) (TREE_INT_CST_LOW (range)) > 10 * count
+      /* If machine does not have a case insn that compares the
+        bounds, this means extra overhead for dispatch tables
+        which raises the threshold for using them.  */
+#define CASE_VALUES_THRESHOLD 5
+#endif /* HAVE_casesi */
+#endif /* CASE_VALUES_THRESHOLD */
+
+      else if (TREE_INT_CST_HIGH (range) != 0
+              || count < CASE_VALUES_THRESHOLD
+              || ((unsigned HOST_WIDE_INT) (TREE_INT_CST_LOW (range))
+                  > 10 * count)
               || TREE_CODE (index_expr) == INTEGER_CST
               /* These will reduce to a constant.  */
               || (TREE_CODE (index_expr) == CALL_EXPR
@@ -3559,7 +3674,7 @@ expand_end_case (orig_index)
               || (TREE_CODE (index_expr) == COMPOUND_EXPR
                   && TREE_CODE (TREE_OPERAND (index_expr, 1)) == INTEGER_CST))
        {
-         index = expand_expr (index_expr, 0, VOIDmode, 0);
+         index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
 
          /* If the index is a short or char that we do not have
             an insn to handle comparisons directly, convert it to
@@ -3636,9 +3751,9 @@ expand_end_case (orig_index)
 
              use_cost_table
                = (TREE_CODE (TREE_TYPE (orig_index)) != ENUMERAL_TYPE
-                  && default_label != 0
                   && estimate_case_costs (thiscase->data.case_stmt.case_list));
-             balance_case_nodes (&thiscase->data.case_stmt.case_list, 0);
+             balance_case_nodes (&thiscase->data.case_stmt.case_list, 
+                                 NULL_PTR);
              emit_case_nodes (index, thiscase->data.case_stmt.case_list,
                               default_label, TREE_TYPE (index_expr));
              emit_jump_if_reachable (default_label);
@@ -3651,26 +3766,40 @@ expand_end_case (orig_index)
          if (HAVE_casesi)
            {
              enum machine_mode index_mode = SImode;
-             tree index_type = GET_MODE_BITSIZE (index_mode);
+             int index_bits = GET_MODE_BITSIZE (index_mode);
 
              /* Convert the index to SImode.  */
              if (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (index_expr)))
                  > GET_MODE_BITSIZE (index_mode))
                {
+                 enum machine_mode omode = TYPE_MODE (TREE_TYPE (index_expr));
+                 rtx rangertx = expand_expr (range, NULL_RTX, VOIDmode, 0);
+
+                 /* We must handle the endpoints in the original mode.  */
                  index_expr = build (MINUS_EXPR, TREE_TYPE (index_expr),
                                      index_expr, minval);
                  minval = integer_zero_node;
+                 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
+                 emit_cmp_insn (rangertx, index, LTU, NULL_RTX, omode, 0, 0);
+                 emit_jump_insn (gen_bltu (default_label));
+                 /* Now we can safely truncate.  */
+                 index = convert_to_mode (index_mode, index, 0);
+               }
+             else
+               {
+                 if (TYPE_MODE (TREE_TYPE (index_expr)) != index_mode)
+                   index_expr = convert (type_for_size (index_bits, 0),
+                                         index_expr);
+                 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
                }
-             if (TYPE_MODE (TREE_TYPE (index_expr)) != index_mode)
-               index_expr = convert (type_for_size (index_type, 0),
-                                     index_expr);
-             index = expand_expr (index_expr, 0, VOIDmode, 0);
              emit_queue ();
              index = protect_from_queue (index, 0);
              do_pending_stack_adjust ();
 
-             emit_jump_insn (gen_casesi (index, expand_expr (minval, 0, VOIDmode, 0),
-                                         expand_expr (range, 0, VOIDmode, 0),
+             emit_jump_insn (gen_casesi (index, expand_expr (minval, NULL_RTX,
+                                                             VOIDmode, 0),
+                                         expand_expr (range, NULL_RTX,
+                                                      VOIDmode, 0),
                                          table_label, default_label));
              win = 1;
            }
@@ -3682,15 +3811,13 @@ expand_end_case (orig_index)
                                    fold (build (MINUS_EXPR,
                                                 TREE_TYPE (index_expr),
                                                 index_expr, minval)));
-             index = expand_expr (index_expr, 0, VOIDmode, 0);
-             index = convert_to_mode (Pmode, index, 1);
+             index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
              emit_queue ();
              index = protect_from_queue (index, 0);
              do_pending_stack_adjust ();
 
-             do_tablejump (index, Pmode,
-                           gen_rtx (CONST_INT, VOIDmode,
-                                    TREE_INT_CST_LOW (range)),
+             do_tablejump (index, TYPE_MODE (TREE_TYPE (index_expr)),
+                           expand_expr (range, NULL_RTX, VOIDmode, 0),
                            table_label, default_label);
              win = 1;
            }
@@ -3706,7 +3833,7 @@ expand_end_case (orig_index)
 
          for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
            {
-             register int i
+             register HOST_WIDE_INT i
                = TREE_INT_CST_LOW (n->low) - TREE_INT_CST_LOW (minval);
 
              while (1)
@@ -3729,7 +3856,7 @@ expand_end_case (orig_index)
          emit_label (table_label);
 
          /* This would be a lot nicer if CASE_VECTOR_PC_RELATIVE
-            were an expression, instead of a an #ifdef/#ifndef.  */
+            were an expression, instead of an #ifdef/#ifndef.  */
          if (
 #ifdef CASE_VECTOR_PC_RELATIVE
              1 ||
@@ -3752,7 +3879,8 @@ expand_end_case (orig_index)
 #endif
        }
 
-      reorder_insns (NEXT_INSN (before_case), get_last_insn (),
+      before_case = squeeze_notes (NEXT_INSN (before_case), get_last_insn ());
+      reorder_insns (before_case, get_last_insn (),
                     thiscase->data.case_stmt.start);
     }
   if (thiscase->exit_label)
@@ -3781,7 +3909,7 @@ do_jump_if_equal (op1, op2, label, unsignedp)
       enum machine_mode mode = GET_MODE (op1);
       if (mode == VOIDmode)
        mode = GET_MODE (op2);
-      emit_cmp_insn (op1, op2, EQ, 0, mode, unsignedp, 0);
+      emit_cmp_insn (op1, op2, EQ, NULL_RTX, mode, unsignedp, 0);
       emit_jump_insn (gen_beq (label));
     }
 }
@@ -3910,7 +4038,7 @@ group_case_nodes (head)
 
 /* Take an ordered list of case nodes
    and transform them into a near optimal binary tree,
-   on the assumtion that any target code selection value is as
+   on the assumption that any target code selection value is as
    likely as any other.
 
    The transformation is performed by splitting the ordered
@@ -4162,7 +4290,7 @@ emit_jump_if_reachable (label)
    current node are arranged to target the subordinates associated
    code for out of bound conditions on the current node node.
 
-   We can asume that when control reaches the code generated here,
+   We can assume that when control reaches the code generated here,
    the index value has already been compared with the parents
    of this node, and determined to be on the same side of each parent
    as this node is.  Thus, if this node tests for the value 51,
@@ -4196,7 +4324,7 @@ emit_case_nodes (index, node, default_label, index_type)
       /* 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, expand_expr (node->low, 0, VOIDmode, 0),
+      do_jump_if_equal (index, expand_expr (node->low, NULL_RTX, VOIDmode, 0),
                        label_rtx (node->code_label), unsignedp);
 
       if (node->right != 0 && node->left != 0)
@@ -4209,8 +4337,9 @@ emit_case_nodes (index, node, default_label, index_type)
 
          if (node_is_bounded (node->right, index_type))
            {
-             emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0),
-                            GT, 0, mode, unsignedp, 0);
+             emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
+                                                VOIDmode, 0),
+                            GT, NULL_RTX, mode, unsignedp, 0);
 
              emit_jump_insn ((*gen_bgt_pat) (label_rtx (node->right->code_label)));
              emit_case_nodes (index, node->left, default_label, index_type);
@@ -4218,9 +4347,9 @@ emit_case_nodes (index, node, default_label, index_type)
 
          else if (node_is_bounded (node->left, index_type))
            {
-             emit_cmp_insn (index, expand_expr (node->high, 0,
+             emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
                                                 VOIDmode, 0),
-                            LT, 0, mode, unsignedp, 0);
+                            LT, NULL_RTX, mode, unsignedp, 0);
              emit_jump_insn ((*gen_blt_pat) (label_rtx (node->left->code_label)));
              emit_case_nodes (index, node->right, default_label, index_type);
            }
@@ -4234,9 +4363,9 @@ emit_case_nodes (index, node, default_label, index_type)
                = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
 
              /* See if the value is on the right.  */
-             emit_cmp_insn (index, expand_expr (node->high, 0,
+             emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
                                                 VOIDmode, 0),
-                            GT, 0, mode, unsignedp, 0);
+                            GT, NULL_RTX, mode, unsignedp, 0);
              emit_jump_insn ((*gen_bgt_pat) (label_rtx (test_label)));
 
              /* Value must be on the left.
@@ -4265,8 +4394,9 @@ emit_case_nodes (index, node, default_label, index_type)
            {
              if (!node_has_low_bound (node, index_type))
                {
-                 emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0),
-                                LT, 0, mode, unsignedp, 0);
+                 emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
+                                                    VOIDmode, 0),
+                                LT, NULL_RTX, mode, unsignedp, 0);
                  emit_jump_insn ((*gen_blt_pat) (default_label));
                }
 
@@ -4277,7 +4407,8 @@ emit_case_nodes (index, node, default_label, index_type)
               since we haven't ruled out the numbers less than
               this node's value.  So handle node->right explicitly.  */
            do_jump_if_equal (index,
-                             expand_expr (node->right->low, 0, VOIDmode, 0),
+                             expand_expr (node->right->low, NULL_RTX,
+                                          VOIDmode, 0),
                              label_rtx (node->right->code_label), unsignedp);
        }
 
@@ -4303,8 +4434,9 @@ emit_case_nodes (index, node, default_label, index_type)
            {
              if (!node_has_high_bound (node, index_type))
                {
-                 emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0),
-                                GT, 0, mode, unsignedp, 0);
+                 emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
+                                                    VOIDmode, 0),
+                                GT, NULL_RTX, mode, unsignedp, 0);
                  emit_jump_insn ((*gen_bgt_pat) (default_label));
                }
 
@@ -4315,7 +4447,8 @@ emit_case_nodes (index, node, default_label, index_type)
               since we haven't ruled out the numbers less than
               this node's value.  So handle node->left explicitly.  */
            do_jump_if_equal (index,
-                             expand_expr (node->left->low, 0, VOIDmode, 0),
+                             expand_expr (node->left->low, NULL_RTX,
+                                          VOIDmode, 0),
                              label_rtx (node->left->code_label), unsignedp);
        }
     }
@@ -4334,8 +4467,9 @@ emit_case_nodes (index, node, default_label, index_type)
             then handle the two subtrees.  */
          tree test_label = 0;
 
-         emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0),
-                        GT, 0, mode, unsignedp, 0);
+         emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
+                                            VOIDmode, 0),
+                        GT, NULL_RTX, mode, unsignedp, 0);
 
          if (node_is_bounded (node->right, index_type))
            /* Right hand node is fully bounded so we can eliminate any
@@ -4352,8 +4486,8 @@ emit_case_nodes (index, node, default_label, index_type)
 
          /* Value belongs to this node or to the left-hand subtree.  */
 
-         emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0),
-                        GE, 0, mode, unsignedp, 0);
+         emit_cmp_insn (index, expand_expr (node->low, NULL_RTX, VOIDmode, 0),
+                        GE, NULL_RTX, mode, unsignedp, 0);
          emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label)));
 
          /* Handle the left-hand subtree.  */
@@ -4378,15 +4512,17 @@ emit_case_nodes (index, node, default_label, index_type)
             if they are possible.  */
          if (!node_has_low_bound (node, index_type))
            {
-             emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0),
-                            LT, 0, mode, unsignedp, 0);
+             emit_cmp_insn (index, expand_expr (node->low, NULL_RTX,
+                                                VOIDmode, 0),
+                            LT, NULL_RTX, mode, unsignedp, 0);
              emit_jump_insn ((*gen_blt_pat) (default_label));
            }
 
          /* Value belongs to this node or to the right-hand subtree.  */
 
-         emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0),
-                        LE, 0, mode, unsignedp, 0);
+         emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
+                                            VOIDmode, 0),
+                        LE, NULL_RTX, mode, unsignedp, 0);
          emit_jump_insn ((*gen_ble_pat) (label_rtx (node->code_label)));
 
          emit_case_nodes (index, node->right, default_label, index_type);
@@ -4398,15 +4534,16 @@ emit_case_nodes (index, node, default_label, index_type)
             if they are possible.  */
          if (!node_has_high_bound (node, index_type))
            {
-             emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0),
-                            GT, 0, mode, unsignedp, 0);
+             emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
+                                                VOIDmode, 0),
+                            GT, NULL_RTX, mode, unsignedp, 0);
              emit_jump_insn ((*gen_bgt_pat) (default_label));
            }
 
          /* Value belongs to this node or to the left-hand subtree.  */
 
-         emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0),
-                        GE, 0, mode, unsignedp, 0);
+         emit_cmp_insn (index, expand_expr (node->low, NULL_RTX, VOIDmode, 0),
+                        GE, NULL_RTX, mode, unsignedp, 0);
          emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label)));
 
          emit_case_nodes (index, node->left, default_label, index_type);
@@ -4420,15 +4557,17 @@ emit_case_nodes (index, node, default_label, index_type)
 
          if (!node_has_high_bound (node, index_type))
            {
-             emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0),
-                            GT, 0, mode, unsignedp, 0);
+             emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
+                                                VOIDmode, 0),
+                            GT, NULL_RTX, mode, unsignedp, 0);
              emit_jump_insn ((*gen_bgt_pat) (default_label));
            }
 
          if (!node_has_low_bound (node, index_type))
            {
-             emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0),
-                            LT, 0, mode, unsignedp, 0);
+             emit_cmp_insn (index, expand_expr (node->low, NULL_RTX,
+                                                VOIDmode, 0),
+                            LT, NULL_RTX, mode, unsignedp, 0);
              emit_jump_insn ((*gen_blt_pat) (default_label));
            }
 
@@ -4440,168 +4579,27 @@ emit_case_nodes (index, node, default_label, index_type)
 /* These routines are used by the loop unrolling code.  They copy BLOCK trees
    so that the debugging info will be correct for the unrolled loop.  */
 
-/* Indexed by loop number, contains pointer to the first block in the loop,
-   or zero if none.  Only valid if doing loop unrolling and outputting debugger
-   info.  */
+/* Indexed by block number, contains a pointer to the N'th block node.  */
 
-tree *loop_number_first_block;
-
-/* Indexed by loop number, contains pointer to the last block in the loop,
-   only valid if loop_number_first_block is nonzero.  */
-
-tree *loop_number_last_block;
-
-/* Indexed by loop number, contains nesting level of first block in the
-   loop, if any.  Only valid if doing loop unrolling and outputting debugger
-   info.  */
-
-int *loop_number_block_level;
-
-/* Scan the function looking for loops, and walk the BLOCK tree at the
-   same time.  Record the first and last BLOCK tree corresponding to each
-   loop.  This function is similar to find_and_verify_loops in loop.c.  */
+static tree *block_vector;
 
 void
-find_loop_tree_blocks (f)
-     rtx f;
+find_loop_tree_blocks ()
 {
-  rtx insn;
-  int current_loop = -1;
-  int next_loop = -1;
-  int loop;
-  int block_level, tree_level;
-  tree tree_block, parent_tree_block;
-
-  tree_block = DECL_INITIAL (current_function_decl);
-  parent_tree_block = 0;
-  block_level = 0;
-  tree_level = -1;
-
-  /* Find boundaries of loops, and save the first and last BLOCK tree
-     corresponding to each loop.  */
-
-  for (insn = f; insn; insn = NEXT_INSN (insn))
-    {
-      if (GET_CODE (insn) == NOTE)
-       switch (NOTE_LINE_NUMBER (insn))
-         {
-         case NOTE_INSN_LOOP_BEG:
-           loop_number_block_level[++next_loop] = block_level;
-           loop_number_first_block[next_loop] = 0;
-           current_loop = next_loop;
-           break;
-
-         case NOTE_INSN_LOOP_END:
-           if (current_loop == -1)
-             abort ();
-
-           current_loop = loop_outer_loop[current_loop];
-           break;
-
-         case NOTE_INSN_BLOCK_BEG:
-           if (tree_level < block_level)
-             {
-               /* We have seen two NOTE_INSN_BLOCK_BEG notes in a row, so
-                  we must now visit the subtree of the current block.  */
-               parent_tree_block = tree_block;
-               tree_block = BLOCK_SUBBLOCKS (tree_block);
-               tree_level++;
-             }
-           else if (tree_level > block_level)
-             abort ();
-
-           /* Save this block tree here for all nested loops for which
-              this is the topmost block.  */
-           for (loop = current_loop;
-                loop != -1 && block_level == loop_number_block_level[loop];
-                loop = loop_outer_loop[loop])
-             {
-               if (loop_number_first_block[loop] == 0)
-                 loop_number_first_block[loop] = tree_block;
-               loop_number_last_block[loop] = tree_block;
-             }
+  tree block = DECL_INITIAL (current_function_decl);
 
-           block_level++;
-           break;
+  /* There first block is for the function body, and does not have
+     corresponding block notes.  Don't include it in the block vector.  */
+  block = BLOCK_SUBBLOCKS (block);
 
-         case NOTE_INSN_BLOCK_END:
-           block_level--;
-           if (tree_level > block_level)
-             {
-               /* We have seen two NOTE_INSN_BLOCK_END notes in a row, so
-                  we must now visit the parent of the current tree.  */
-               if (tree_block != 0 || parent_tree_block == 0)
-                 abort ();
-               tree_block = parent_tree_block;
-               parent_tree_block = BLOCK_SUPERCONTEXT (parent_tree_block);
-               tree_level--;
-             }
-           tree_block = BLOCK_CHAIN (tree_block);
-           break;
-         }
-    }
+  block_vector = identify_blocks (block, get_insns ());
 }
 
-/* This routine will make COPIES-1 copies of all BLOCK trees that correspond
-   to BLOCK_BEG notes inside the loop LOOP_NUMBER.
-
-   Note that we only copy the topmost level of tree nodes; they will share
-   pointers to the same subblocks.  */
-
 void
-unroll_block_trees (loop_number, copies)
-     int loop_number;
-     int copies;
+unroll_block_trees ()
 {
-  int i;
+  tree block = DECL_INITIAL (current_function_decl);
 
-  /* First check whether there are any blocks that need to be copied.  */
-  if (loop_number_first_block[loop_number])
-    {
-      tree first_block = loop_number_first_block[loop_number];
-      tree last_block = loop_number_last_block[loop_number];
-      tree last_block_created = 0;
-
-      for (i = 0; i < copies - 1; i++)
-       {
-         tree block = first_block;
-         tree insert_after = last_block;
-         tree copied_block;
-
-         /* Copy every block between first_block and last_block inclusive,
-            inserting the new blocks after last_block.  */
-         do
-           {
-             tree new_block = make_node (BLOCK);
-             BLOCK_VARS (new_block) = BLOCK_VARS (block);
-             BLOCK_TYPE_TAGS (new_block) = BLOCK_TYPE_TAGS (block);
-             BLOCK_SUBBLOCKS (new_block) = BLOCK_SUBBLOCKS (block);
-             BLOCK_SUPERCONTEXT (new_block) = BLOCK_SUPERCONTEXT (block);
-             TREE_USED (new_block) = TREE_USED (block);
-
-             /* Insert the new block after the insertion point, and move
-                the insertion point to the new block.  This ensures that
-                the copies are inserted in the right order.  */
-             BLOCK_CHAIN (new_block) = BLOCK_CHAIN (insert_after);
-             BLOCK_CHAIN (insert_after) = new_block;
-             insert_after = new_block;
-
-             copied_block = block;
-             block = BLOCK_CHAIN (block);
-           }
-         while (copied_block != last_block);
-
-         /* Remember the last block created, so that we can update the
-            info in the tables.  */
-         if (last_block_created == 0)
-           last_block_created = insert_after;
-       }
-
-      /* For all nested loops for which LAST_BLOCK was originally the last
-        block, update the tables to indicate that LAST_BLOCK_CREATED is
-        now the last block in the loop.  */
-      for (i = loop_number; last_block == loop_number_last_block[i];
-          i = loop_outer_loop[i])
-       loop_number_last_block[i] = last_block_created;
-    }
+  reorder_blocks (block_vector, block, get_insns ());
 }
+
This page took 0.061086 seconds and 5 git commands to generate.