re PR debug/66691 (ICE on valid code at -O3 with -g enabled in simplify_subreg, at...
[gcc.git] / gcc / cfgrtl.c
index ec53f2e752c8e4198a98d9daaa93e776c981332d..2e33dda2f81581062ad411a7234e54e5e4110dfe 100644 (file)
@@ -1,5 +1,5 @@
 /* Control flow graph manipulation code for GNU compiler.
-   Copyright (C) 1987-2014 Free Software Foundation, Inc.
+   Copyright (C) 1987-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -41,41 +41,56 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "alias.h"
+#include "symtab.h"
 #include "tree.h"
 #include "hard-reg-set.h"
+#include "predict.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "cfgbuild.h"
+#include "cfgcleanup.h"
 #include "basic-block.h"
 #include "bb-reorder.h"
 #include "regs.h"
 #include "flags.h"
-#include "function.h"
 #include "except.h"
 #include "rtl-error.h"
 #include "tm_p.h"
 #include "obstack.h"
 #include "insn-attr.h"
 #include "insn-config.h"
+#include "rtl.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
 #include "expr.h"
 #include "target.h"
 #include "common/common-target.h"
 #include "cfgloop.h"
-#include "ggc.h"
 #include "tree-pass.h"
 #include "df.h"
 
 /* Holds the interesting leading and trailing notes for the function.
    Only applicable if the CFG is in cfglayout mode.  */
-static GTY(()) rtx cfg_layout_function_footer;
-static GTY(()) rtx cfg_layout_function_header;
+static GTY(()) rtx_insn *cfg_layout_function_footer;
+static GTY(()) rtx_insn *cfg_layout_function_header;
 
-static rtx skip_insns_after_block (basic_block);
+static rtx_insn *skip_insns_after_block (basic_block);
 static void record_effective_endpoints (void);
-static rtx label_for_bb (basic_block);
 static void fixup_reorder_chain (void);
 
 void verify_insn_chain (void);
 static void fixup_fallthru_exit_predecessor (void);
-static int can_delete_note_p (const_rtx);
-static int can_delete_label_p (const_rtx);
+static int can_delete_note_p (const rtx_note *);
+static int can_delete_label_p (const rtx_code_label *);
 static basic_block rtl_split_edge (edge);
 static bool rtl_move_block_after (basic_block, basic_block);
 static int rtl_verify_flow_info (void);
@@ -95,7 +110,7 @@ static void rtl_make_forwarder_block (edge);
    so that we may simply delete it.  */
 
 static int
-can_delete_note_p (const_rtx note)
+can_delete_note_p (const rtx_note *note)
 {
   switch (NOTE_KIND (note))
     {
@@ -112,19 +127,20 @@ can_delete_note_p (const_rtx note)
 /* True if a given label can be deleted.  */
 
 static int
-can_delete_label_p (const_rtx label)
+can_delete_label_p (const rtx_code_label *label)
 {
   return (!LABEL_PRESERVE_P (label)
          /* User declared labels must be preserved.  */
          && LABEL_NAME (label) == 0
-         && !in_expr_list_p (forced_labels, label));
+         && !in_insn_list_p (forced_labels, label));
 }
 
 /* Delete INSN by patching it out.  */
 
 void
-delete_insn (rtx insn)
+delete_insn (rtx uncast_insn)
 {
+  rtx_insn *insn = as_a <rtx_insn *> (uncast_insn);
   rtx note;
   bool really_delete = true;
 
@@ -133,11 +149,11 @@ delete_insn (rtx insn)
       /* Some labels can't be directly removed from the INSN chain, as they
         might be references via variables, constant pool etc.
         Convert them to the special NOTE_INSN_DELETED_LABEL note.  */
-      if (! can_delete_label_p (insn))
+      if (! can_delete_label_p (as_a <rtx_code_label *> (insn)))
        {
          const char *name = LABEL_NAME (insn);
          basic_block bb = BLOCK_FOR_INSN (insn);
-         rtx bb_note = NEXT_INSN (insn);
+         rtx_insn *bb_note = NEXT_INSN (insn);
 
          really_delete = false;
          PUT_CODE (insn, NOTE);
@@ -152,23 +168,23 @@ delete_insn (rtx insn)
              && bb == BLOCK_FOR_INSN (bb_note))
            {
              reorder_insns_nobb (insn, insn, bb_note);
-             SET_BB_HEAD (bb) = bb_note;
+             BB_HEAD (bb) = bb_note;
              if (BB_END (bb) == bb_note)
-               SET_BB_END (bb) = insn;
+               BB_END (bb) = insn;
            }
        }
 
-      remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels);
+      remove_node_from_insn_list (insn, &nonlocal_goto_handler_labels);
     }
 
   if (really_delete)
     {
       /* If this insn has already been deleted, something is very wrong.  */
-      gcc_assert (!INSN_DELETED_P (insn));
+      gcc_assert (!insn->deleted ());
       if (INSN_P (insn))
        df_insn_delete (insn);
       remove_insn (insn);
-      INSN_DELETED_P (insn) = 1;
+      insn->set_deleted ();
     }
 
   /* If deleting a jump, decrement the use count of the label.  Deleting
@@ -197,16 +213,15 @@ delete_insn (rtx insn)
       remove_note (insn, note);
     }
 
-  if (JUMP_TABLE_DATA_P (insn))
+  if (rtx_jump_table_data *table = dyn_cast <rtx_jump_table_data *> (insn))
     {
-      rtx pat = PATTERN (insn);
-      int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
-      int len = XVECLEN (pat, diff_vec_p);
+      rtvec vec = table->get_labels ();
+      int len = GET_NUM_ELEM (vec);
       int i;
 
       for (i = 0; i < len; i++)
        {
-         rtx label = XEXP (XVECEXP (pat, diff_vec_p, i), 0);
+         rtx label = XEXP (RTVEC_ELT (vec, i), 0);
 
          /* When deleting code in bulk (e.g. removing many unreachable
             blocks) we can delete a label that's a target of the vector
@@ -220,7 +235,7 @@ delete_insn (rtx insn)
 /* Like delete_insn but also purge dead edges from BB.  */
 
 void
-delete_insn_and_edges (rtx insn)
+delete_insn_and_edges (rtx_insn *insn)
 {
   bool purge = false;
 
@@ -240,21 +255,21 @@ delete_insn_and_edges (rtx insn)
 void
 delete_insn_chain (rtx start, rtx finish, bool clear_bb)
 {
-  rtx prev, current;
+  rtx_insn *prev, *current;
 
   /* Unchain the insns one by one.  It would be quicker to delete all of these
      with a single unchaining, rather than one at a time, but we need to keep
      the NOTE's.  */
-  current = finish;
+  current = safe_as_a <rtx_insn *> (finish);
   while (1)
     {
       prev = PREV_INSN (current);
-      if (NOTE_P (current) && !can_delete_note_p (current))
+      if (NOTE_P (current) && !can_delete_note_p (as_a <rtx_note *> (current)))
        ;
       else
        delete_insn (current);
 
-      if (clear_bb && !INSN_DELETED_P (current))
+      if (clear_bb && !current->deleted ())
        set_block_for_insn (current, NULL);
 
       if (current == start)
@@ -272,7 +287,7 @@ delete_insn_chain (rtx start, rtx finish, bool clear_bb)
    AFTER is the basic block we should be put after.  */
 
 basic_block
-create_basic_block_structure (rtx head, rtx end, rtx_note *bb_note,
+create_basic_block_structure (rtx_insn *head, rtx_insn *end, rtx_note *bb_note,
                              basic_block after)
 {
   basic_block bb;
@@ -283,7 +298,7 @@ create_basic_block_structure (rtx head, rtx end, rtx_note *bb_note,
     {
       /* If we found an existing note, thread it back onto the chain.  */
 
-      rtx after;
+      rtx_insn *after;
 
       if (LABEL_P (head))
        after = head;
@@ -327,8 +342,8 @@ create_basic_block_structure (rtx head, rtx end, rtx_note *bb_note,
   if (NEXT_INSN (end) == bb_note)
     end = bb_note;
 
-  SET_BB_HEAD (bb) = head;
-  SET_BB_END (bb) = end;
+  BB_HEAD (bb) = head;
+  BB_END (bb) = end;
   bb->index = last_basic_block_for_fn (cfun)++;
   bb->flags = BB_NEW | BB_RTL;
   link_block (bb, after);
@@ -352,7 +367,8 @@ create_basic_block_structure (rtx head, rtx end, rtx_note *bb_note,
 static basic_block
 rtl_create_basic_block (void *headp, void *endp, basic_block after)
 {
-  rtx head = (rtx) headp, end = (rtx) endp;
+  rtx_insn *head = (rtx_insn *) headp;
+  rtx_insn *end = (rtx_insn *) endp;
   basic_block bb;
 
   /* Grow the basic block array if needed.  */
@@ -391,7 +407,7 @@ cfg_layout_create_basic_block (void *head, void *end, basic_block after)
 static void
 rtl_delete_block (basic_block b)
 {
-  rtx insn, end;
+  rtx_insn *insn, *end;
 
   /* If the head of this block is a CODE_LABEL, then it might be the
      label for an exception handler which can't be reached.  We need
@@ -401,7 +417,7 @@ rtl_delete_block (basic_block b)
   end = get_last_bb_insn (b);
 
   /* Selectively delete the entire chain.  */
-  SET_BB_HEAD (b) = NULL;
+  BB_HEAD (b) = NULL;
   delete_insn_chain (insn, end, true);
 
 
@@ -419,8 +435,8 @@ compute_bb_for_insn (void)
 
   FOR_EACH_BB_FN (bb, cfun)
     {
-      rtx end = BB_END (bb);
-      rtx insn;
+      rtx_insn *end = BB_END (bb);
+      rtx_insn *insn;
 
       for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
        {
@@ -436,7 +452,7 @@ compute_bb_for_insn (void)
 unsigned int
 free_bb_for_insn (void)
 {
-  rtx insn;
+  rtx_insn *insn;
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     if (!BARRIER_P (insn))
       BLOCK_FOR_INSN (insn) = NULL;
@@ -525,9 +541,9 @@ emit_insn_at_entry (rtx insn)
    (i.e. both BEGIN and END will be updated. */
 
 static void
-update_bb_for_insn_chain (rtx begin, rtx end, basic_block bb)
+update_bb_for_insn_chain (rtx_insn *begin, rtx_insn *end, basic_block bb)
 {
-  rtx insn;
+  rtx_insn *insn;
 
   end = NEXT_INSN (end);
   for (insn = begin; insn != end; insn = NEXT_INSN (insn))
@@ -549,7 +565,7 @@ update_bb_for_insn (basic_block bb)
    even after reload.  */
 
 static bool
-flow_active_insn_p (const_rtx insn)
+flow_active_insn_p (const rtx_insn *insn)
 {
   if (active_insn_p (insn))
     return true;
@@ -573,7 +589,7 @@ flow_active_insn_p (const_rtx insn)
 bool
 contains_no_active_insn_p (const_basic_block bb)
 {
-  rtx insn;
+  rtx_insn *insn;
 
   if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun) || bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)
       || !single_succ_p (bb))
@@ -617,8 +633,8 @@ forwarder_block_p (const_basic_block bb)
 bool
 can_fallthru (basic_block src, basic_block target)
 {
-  rtx insn = BB_END (src);
-  rtx insn2;
+  rtx_insn *insn = BB_END (src);
+  rtx_insn *insn2;
   edge e;
   edge_iterator ei;
 
@@ -665,7 +681,7 @@ could_fall_through (basic_block src, basic_block target)
 rtx_note *
 bb_note (basic_block bb)
 {
-  rtx note;
+  rtx_insn *note;
 
   note = BB_HEAD (bb);
   if (LABEL_P (note))
@@ -678,16 +694,16 @@ bb_note (basic_block bb)
 /* Return the INSN immediately following the NOTE_INSN_BASIC_BLOCK
    note associated with the BLOCK.  */
 
-static rtx
+static rtx_insn *
 first_insn_after_basic_block_note (basic_block block)
 {
-  rtx insn;
+  rtx_insn *insn;
 
   /* Get the first instruction in the block.  */
   insn = BB_HEAD (block);
 
   if (insn == NULL_RTX)
-    return NULL_RTX;
+    return NULL;
   if (LABEL_P (insn))
     insn = NEXT_INSN (insn);
   gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn));
@@ -695,14 +711,14 @@ first_insn_after_basic_block_note (basic_block block)
   return NEXT_INSN (insn);
 }
 
-/* Creates a new basic block just after basic block B by splitting
-   everything after specified instruction I.  */
+/* Creates a new basic block just after basic block BB by splitting
+   everything after specified instruction INSNP.  */
 
 static basic_block
 rtl_split_block (basic_block bb, void *insnp)
 {
   basic_block new_bb;
-  rtx insn = (rtx) insnp;
+  rtx_insn *insn = (rtx_insn *) insnp;
   edge e;
   edge_iterator ei;
 
@@ -712,7 +728,7 @@ rtl_split_block (basic_block bb, void *insnp)
 
       if (insn)
        {
-         rtx next = insn;
+         rtx_insn *next = insn;
 
          insn = PREV_INSN (insn);
 
@@ -744,7 +760,7 @@ rtl_split_block (basic_block bb, void *insnp)
   /* Create the new basic block.  */
   new_bb = create_basic_block (NEXT_INSN (insn), BB_END (bb), bb);
   BB_COPY_PARTITION (new_bb, bb);
-  SET_BB_END (bb) = insn;
+  BB_END (bb) = insn;
 
   /* Redirect the outgoing edges.  */
   new_bb->succs = bb->succs;
@@ -764,7 +780,7 @@ static bool
 unique_locus_on_edge_between_p (basic_block a, basic_block b)
 {
   const location_t goto_locus = EDGE_SUCC (a, 0)->goto_locus;
-  rtx insn, end;
+  rtx_insn *insn, *end;
 
   if (LOCATION_LOCUS (goto_locus) == UNKNOWN_LOCATION)
     return false;
@@ -803,7 +819,7 @@ emit_nop_for_unique_locus_between (basic_block a, basic_block b)
   if (!unique_locus_on_edge_between_p (a, b))
     return;
 
-  SET_BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
+  BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
   INSN_LOCATION (BB_END (a)) = EDGE_SUCC (a, 0)->goto_locus;
 }
 
@@ -813,9 +829,9 @@ emit_nop_for_unique_locus_between (basic_block a, basic_block b)
 static void
 rtl_merge_blocks (basic_block a, basic_block b)
 {
-  rtx b_head = BB_HEAD (b), b_end = BB_END (b), a_end = BB_END (a);
-  rtx del_first = NULL_RTX, del_last = NULL_RTX;
-  rtx b_debug_start = b_end, b_debug_end = b_end;
+  rtx_insn *b_head = BB_HEAD (b), *b_end = BB_END (b), *a_end = BB_END (a);
+  rtx_insn *del_first = NULL, *del_last = NULL;
+  rtx_insn *b_debug_start = b_end, *b_debug_end = b_end;
   bool forwarder_p = (b->flags & BB_FORWARDER_BLOCK) != 0;
   int b_empty = 0;
 
@@ -854,7 +870,7 @@ rtl_merge_blocks (basic_block a, basic_block b)
   /* If there was a jump out of A, delete it.  */
   if (JUMP_P (a_end))
     {
-      rtx prev;
+      rtx_insn *prev;
 
       for (prev = PREV_INSN (a_end); ; prev = PREV_INSN (prev))
        if (!NOTE_P (prev)
@@ -864,19 +880,17 @@ rtl_merge_blocks (basic_block a, basic_block b)
 
       del_first = a_end;
 
-#ifdef HAVE_cc0
       /* If this was a conditional jump, we need to also delete
         the insn that set cc0.  */
-      if (only_sets_cc0_p (prev))
+      if (HAVE_cc0 && only_sets_cc0_p (prev))
        {
-         rtx tmp = prev;
+         rtx_insn *tmp = prev;
 
          prev = prev_nonnote_insn (prev);
          if (!prev)
            prev = BB_HEAD (a);
          del_first = tmp;
        }
-#endif
 
       a_end = PREV_INSN (del_first);
     }
@@ -885,8 +899,8 @@ rtl_merge_blocks (basic_block a, basic_block b)
 
   /* Delete everything marked above as well as crap that might be
      hanging out between the two blocks.  */
-  SET_BB_END (a) = a_end;
-  SET_BB_HEAD (b) = b_empty ? NULL_RTX : b_head;
+  BB_END (a) = a_end;
+  BB_HEAD (b) = b_empty ? NULL : b_head;
   delete_insn_chain (del_first, del_last, true);
 
   /* When not optimizing and the edge is the only place in RTL which holds
@@ -902,8 +916,8 @@ rtl_merge_blocks (basic_block a, basic_block b)
     {
       update_bb_for_insn_chain (a_end, b_debug_end, a);
 
-      SET_BB_END (a) = b_debug_end;
-      SET_BB_HEAD (b) = NULL_RTX;
+      BB_END (a) = b_debug_end;
+      BB_HEAD (b) = NULL;
     }
   else if (b_end != b_debug_end)
     {
@@ -915,7 +929,7 @@ rtl_merge_blocks (basic_block a, basic_block b)
        reorder_insns_nobb (NEXT_INSN (a_end), PREV_INSN (b_debug_start),
                            b_debug_end);
       update_bb_for_insn_chain (b_debug_start, b_debug_end, a);
-      SET_BB_END (a) = b_debug_end;
+      BB_END (a) = b_debug_end;
     }
 
   df_bb_delete (b->index);
@@ -972,18 +986,18 @@ rtl_can_merge_blocks (basic_block a, basic_block b)
 /* Return the label in the head of basic block BLOCK.  Create one if it doesn't
    exist.  */
 
-rtx
+rtx_code_label *
 block_label (basic_block block)
 {
   if (block == EXIT_BLOCK_PTR_FOR_FN (cfun))
-    return NULL_RTX;
+    return NULL;
 
   if (!LABEL_P (BB_HEAD (block)))
     {
-      SET_BB_HEAD (block) = emit_label_before (gen_label_rtx (), BB_HEAD (block));
+      BB_HEAD (block) = emit_label_before (gen_label_rtx (), BB_HEAD (block));
     }
 
-  return BB_HEAD (block);
+  return as_a <rtx_code_label *> (BB_HEAD (block));
 }
 
 /* Attempt to perform edge redirection by replacing possibly complex jump
@@ -995,7 +1009,7 @@ edge
 try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
 {
   basic_block src = e->src;
-  rtx insn = BB_END (src), kill_from;
+  rtx_insn *insn = BB_END (src), *kill_from;
   rtx set;
   int fallthru = 0;
 
@@ -1035,11 +1049,9 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
   /* In case we zap a conditional jump, we'll need to kill
      the cc0 setter too.  */
   kill_from = insn;
-#ifdef HAVE_cc0
-  if (reg_mentioned_p (cc0_rtx, PATTERN (insn))
+  if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, PATTERN (insn))
       && only_sets_cc0_p (PREV_INSN (insn)))
     kill_from = PREV_INSN (insn);
-#endif
 
   /* See if we can create the fallthru edge.  */
   if (in_cfglayout || can_fallthru (src, target))
@@ -1051,7 +1063,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
       /* Selectively unlink whole insn chain.  */
       if (in_cfglayout)
        {
-         rtx insn = BB_FOOTER (src);
+         rtx_insn *insn = BB_FOOTER (src);
 
          delete_insn_chain (kill_from, BB_END (src), false);
 
@@ -1063,7 +1075,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
                  if (PREV_INSN (insn))
                    SET_NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
                  else
-                   SET_BB_FOOTER (src) = NEXT_INSN (insn);
+                   BB_FOOTER (src) = NEXT_INSN (insn);
                  if (NEXT_INSN (insn))
                    SET_PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
                }
@@ -1085,7 +1097,8 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
       if (dump_file)
        fprintf (dump_file, "Redirecting jump %i from %i to %i.\n",
                 INSN_UID (insn), e->dest->index, target->index);
-      if (!redirect_jump (insn, block_label (target), 0))
+      if (!redirect_jump (as_a <rtx_jump_insn *> (insn),
+                         block_label (target), 0))
        {
          gcc_assert (target == EXIT_BLOCK_PTR_FOR_FN (cfun));
          return NULL;
@@ -1099,8 +1112,9 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
   /* Or replace possibly complicated jump insn by simple jump insn.  */
   else
     {
-      rtx target_label = block_label (target);
-      rtx barrier, label;
+      rtx_code_label *target_label = block_label (target);
+      rtx_insn *barrier;
+      rtx label;
       rtx_jump_table_data *table;
 
       emit_jump_insn_after_noloc (gen_jump (target_label), insn);
@@ -1129,7 +1143,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
              /* Move the jump before barrier so that the notes
                 which originally were or were created before jump table are
                 inside the basic block.  */
-             rtx new_insn = BB_END (src);
+             rtx_insn *new_insn = BB_END (src);
 
              update_bb_for_insn_chain (NEXT_INSN (BB_END (src)),
                                        PREV_INSN (barrier), src);
@@ -1172,7 +1186,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
    doesn't work.  */
 
 static bool
-patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
+patch_jump_insn (rtx_insn *insn, rtx_insn *old_label, basic_block new_bb)
 {
   rtx_jump_table_data *table;
   rtx tmp;
@@ -1181,14 +1195,11 @@ patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
     {
       rtvec vec;
       int j;
-      rtx new_label = block_label (new_bb);
+      rtx_code_label *new_label = block_label (new_bb);
 
       if (new_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
        return false;
-      if (GET_CODE (PATTERN (table)) == ADDR_VEC)
-       vec = XVEC (PATTERN (table), 0);
-      else
-       vec = XVEC (PATTERN (table), 1);
+      vec = table->get_labels ();
 
       for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
        if (XEXP (RTVEC_ELT (vec, j), 0) == old_label)
@@ -1203,7 +1214,7 @@ patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
          && SET_DEST (tmp) == pc_rtx
          && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
          && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF
-         && XEXP (XEXP (SET_SRC (tmp), 2), 0) == old_label)
+         && LABEL_REF_LABEL (XEXP (SET_SRC (tmp), 2)) == old_label)
        {
          XEXP (SET_SRC (tmp), 2) = gen_rtx_LABEL_REF (Pmode,
                                                       new_label);
@@ -1214,11 +1225,11 @@ patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
   else if ((tmp = extract_asm_operands (PATTERN (insn))) != NULL)
     {
       int i, n = ASM_OPERANDS_LABEL_LENGTH (tmp);
-      rtx new_label, note;
+      rtx note;
 
       if (new_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
        return false;
-      new_label = block_label (new_bb);
+      rtx_code_label *new_label = block_label (new_bb);
 
       for (i = 0; i < n; ++i)
        {
@@ -1271,7 +1282,8 @@ patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
          /* If the substitution doesn't succeed, die.  This can happen
             if the back end emitted unrecognizable instructions or if
             target is exit block on some arches.  */
-         if (!redirect_jump (insn, block_label (new_bb), 0))
+         if (!redirect_jump (as_a <rtx_jump_insn *> (insn),
+                             block_label (new_bb), 0))
            {
              gcc_assert (new_bb == EXIT_BLOCK_PTR_FOR_FN (cfun));
              return false;
@@ -1287,9 +1299,9 @@ patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
 static edge
 redirect_branch_edge (edge e, basic_block target)
 {
-  rtx old_label = BB_HEAD (e->dest);
+  rtx_insn *old_label = BB_HEAD (e->dest);
   basic_block src = e->src;
-  rtx insn = BB_END (src);
+  rtx_insn *insn = BB_END (src);
 
   /* We can only redirect non-fallthru edges of jump insn.  */
   if (e->flags & EDGE_FALLTHRU)
@@ -1299,7 +1311,7 @@ redirect_branch_edge (edge e, basic_block target)
 
   if (!currently_expanding_to_rtl)
     {
-      if (!patch_jump_insn (insn, old_label, target))
+      if (!patch_jump_insn (as_a <rtx_jump_insn *> (insn), old_label, target))
        return NULL;
     }
   else
@@ -1307,7 +1319,8 @@ redirect_branch_edge (edge e, basic_block target)
        jumps (i.e. not yet split by find_many_sub_basic_blocks).
        Redirect all of those that match our label.  */
     FOR_BB_INSNS (src, insn)
-      if (JUMP_P (insn) && !patch_jump_insn (insn, old_label, target))
+      if (JUMP_P (insn) && !patch_jump_insn (as_a <rtx_jump_insn *> (insn),
+                                            old_label, target))
        return NULL;
 
   if (dump_file)
@@ -1450,7 +1463,24 @@ emit_barrier_after_bb (basic_block bb)
   gcc_assert (current_ir_type () == IR_RTL_CFGRTL
               || current_ir_type () == IR_RTL_CFGLAYOUT);
   if (current_ir_type () == IR_RTL_CFGLAYOUT)
-    SET_BB_FOOTER (bb) = unlink_insn_chain (barrier, barrier);
+    {
+      rtx_insn *insn = unlink_insn_chain (barrier, barrier);
+
+      if (BB_FOOTER (bb))
+       {
+          rtx_insn *footer_tail = BB_FOOTER (bb);
+
+          while (NEXT_INSN (footer_tail))
+            footer_tail = NEXT_INSN (footer_tail);
+          if (!BARRIER_P (footer_tail))
+            {
+              SET_NEXT_INSN (footer_tail) = insn;
+              SET_PREV_INSN (insn) = footer_tail;
+            }
+       }
+      else
+        BB_FOOTER (bb) = insn;
+    }
 }
 
 /* Like force_nonfallthru below, but additionally performs redirection
@@ -1481,7 +1511,8 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
       edge b = unchecked_make_edge (e->src, target, 0);
       bool redirected;
 
-      redirected = redirect_jump (BB_END (e->src), block_label (target), 0);
+      redirected = redirect_jump (as_a <rtx_jump_insn *> (BB_END (e->src)),
+                                 block_label (target), 0);
       gcc_assert (redirected);
 
       note = find_reg_note (BB_END (e->src), REG_BR_PROB, NULL_RTX);
@@ -1575,9 +1606,10 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
        }
       if (adjust_jump_target)
        {
-         rtx insn = BB_END (e->src), note;
-         rtx old_label = BB_HEAD (e->dest);
-         rtx new_label = BB_HEAD (target);
+         rtx_insn *insn = BB_END (e->src);
+         rtx note;
+         rtx_insn *old_label = BB_HEAD (e->dest);
+         rtx_insn *new_label = BB_HEAD (target);
 
          if (JUMP_LABEL (insn) == old_label)
            {
@@ -1603,6 +1635,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
 
   if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags || asm_goto_edge)
     {
+      rtx_insn *new_head;
       gcov_type count = e->count;
       int probability = e->probability;
       /* Create the new structures.  */
@@ -1612,12 +1645,12 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
         forward from the last instruction of the old block.  */
       rtx_jump_table_data *table;
       if (tablejump_p (BB_END (e->src), NULL, &table))
-       note = table;
+       new_head = table;
       else
-       note = BB_END (e->src);
-      note = NEXT_INSN (note);
+       new_head = BB_END (e->src);
+      new_head = NEXT_INSN (new_head);
 
-      jump_block = create_basic_block (note, NULL, e->src);
+      jump_block = create_basic_block (new_head, NULL, e->src);
       jump_block->count = count;
       jump_block->frequency = EDGE_FREQUENCY (e);
 
@@ -1662,28 +1695,19 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
   if (target == EXIT_BLOCK_PTR_FOR_FN (cfun))
     {
       if (jump_label == ret_rtx)
-       {
-#ifdef HAVE_return
-         emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block), loc);
-#else
-         gcc_unreachable ();
-#endif
-       }
+       emit_jump_insn_after_setloc (targetm.gen_return (),
+                                    BB_END (jump_block), loc);
       else
        {
          gcc_assert (jump_label == simple_return_rtx);
-#ifdef HAVE_simple_return
-         emit_jump_insn_after_setloc (gen_simple_return (),
+         emit_jump_insn_after_setloc (targetm.gen_simple_return (),
                                       BB_END (jump_block), loc);
-#else
-         gcc_unreachable ();
-#endif
        }
       set_return_jump_label (BB_END (jump_block));
     }
   else
     {
-      rtx label = block_label (target);
+      rtx_code_label *label = block_label (target);
       emit_jump_insn_after_setloc (gen_jump (label), BB_END (jump_block), loc);
       JUMP_LABEL (BB_END (jump_block)) = label;
       LABEL_NUSES (label)++;
@@ -1735,7 +1759,7 @@ rtl_redirect_edge_and_branch_force (edge e, basic_block target)
 static void
 rtl_tidy_fallthru_edge (edge e)
 {
-  rtx q;
+  rtx_insn *q;
   basic_block b = e->src, c = b->next_bb;
 
   /* ??? In a late-running flow pass, other folks may have deleted basic
@@ -1761,12 +1785,28 @@ rtl_tidy_fallthru_edge (edge e)
       && (any_uncondjump_p (q)
          || single_succ_p (b)))
     {
-#ifdef HAVE_cc0
+      rtx label;
+      rtx_jump_table_data *table;
+
+      if (tablejump_p (q, &label, &table))
+       {
+         /* The label is likely mentioned in some instruction before
+            the tablejump and might not be DCEd, so turn it into
+            a note instead and move before the tablejump that is going to
+            be deleted.  */
+         const char *name = LABEL_NAME (label);
+         PUT_CODE (label, NOTE);
+         NOTE_KIND (label) = NOTE_INSN_DELETED_LABEL;
+         NOTE_DELETED_LABEL_NAME (label) = name;
+         rtx_insn *lab = safe_as_a <rtx_insn *> (label);
+         reorder_insns (lab, lab, PREV_INSN (q));
+         delete_insn (table);
+       }
+
       /* If this was a conditional jump, we need to also delete
         the insn that set cc0.  */
-      if (any_condjump_p (q) && only_sets_cc0_p (PREV_INSN (q)))
+      if (HAVE_cc0 && any_condjump_p (q) && only_sets_cc0_p (PREV_INSN (q)))
        q = PREV_INSN (q);
-#endif
 
       q = PREV_INSN (q);
     }
@@ -1813,7 +1853,7 @@ static basic_block
 rtl_split_edge (edge edge_in)
 {
   basic_block bb, new_bb;
-  rtx before;
+  rtx_insn *before;
 
   /* Abnormal edges cannot be split.  */
   gcc_assert (!(edge_in->flags & EDGE_ABNORMAL));
@@ -1832,7 +1872,7 @@ rtl_split_edge (edge edge_in)
   if (edge_in->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
     before = BB_HEAD (edge_in->dest);
   else
-    before = NULL_RTX;
+    before = NULL;
 
   /* If this is a fall through edge to the exit block, the blocks might be
      not adjacent, and the right place is after the source.  */
@@ -1864,7 +1904,7 @@ rtl_split_edge (edge edge_in)
               && (edge_in->flags & EDGE_CROSSING))
             {
               after = last_bb_in_partition (edge_in->src);
-              before = NEXT_INSN (BB_END (after));
+              before = get_last_bb_insn (after);
               /* The instruction following the last bb in partition should
                  be a barrier, since it cannot end in a fall-through.  */
               gcc_checking_assert (BARRIER_P (before));
@@ -1903,7 +1943,7 @@ rtl_split_edge (edge edge_in)
          /* For asm goto even splitting of fallthru edge might
             need insn patching, as other labels might point to the
             old label.  */
-         rtx last = BB_END (edge_in->src);
+         rtx_insn *last = BB_END (edge_in->src);
          if (last
              && JUMP_P (last)
              && edge_in->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
@@ -1944,12 +1984,12 @@ insert_insn_on_edge (rtx pattern, edge e)
 void
 commit_one_edge_insertion (edge e)
 {
-  rtx before = NULL_RTX, after = NULL_RTX, insns, tmp, last;
+  rtx_insn *before = NULL, *after = NULL, *insns, *tmp, *last;
   basic_block bb;
 
   /* Pull the insns off the edge now since the edge might go away.  */
   insns = e->insns.r;
-  e->insns.r = NULL_RTX;
+  e->insns.r = NULL;
 
   /* Figure out where to put these insns.  If the destination has
      one predecessor, insert there.  Except for the exit block.  */
@@ -2087,8 +2127,8 @@ commit_edge_insertions (void)
 static void
 rtl_dump_bb (FILE *outf, basic_block bb, int indent, int flags)
 {
-  rtx insn;
-  rtx last;
+  rtx_insn *insn;
+  rtx_insn *last;
   char *s_indent;
 
   s_indent = (char *) alloca ((size_t) indent + 1);
@@ -2128,9 +2168,9 @@ rtl_dump_bb (FILE *outf, basic_block bb, int indent, int flags)
    in dumpfile.h.  */
 
 void
-print_rtl_with_bb (FILE *outf, const_rtx rtx_first, int flags)
+print_rtl_with_bb (FILE *outf, const rtx_insn *rtx_first, int flags)
 {
-  const_rtx tmp_rtx;
+  const rtx_insn *tmp_rtx;
   if (rtx_first == 0)
     fprintf (outf, "(nil)\n");
   else
@@ -2155,7 +2195,7 @@ print_rtl_with_bb (FILE *outf, const_rtx rtx_first, int flags)
        {
          FOR_EACH_BB_REVERSE_FN (bb, cfun)
            {
-             rtx x;
+             rtx_insn *x;
 
              start[INSN_UID (BB_HEAD (bb))] = bb;
              end[INSN_UID (BB_END (bb))] = bb;
@@ -2583,7 +2623,7 @@ rtl_verify_edges (void)
 static int
 rtl_verify_bb_insns (void)
 {
-  rtx x;
+  rtx_insn *x;
   int err = 0;
   basic_block bb;
 
@@ -2652,7 +2692,7 @@ rtl_verify_bb_pointers (void)
   /* Check the general integrity of the basic blocks.  */
   FOR_EACH_BB_REVERSE_FN (bb, cfun)
     {
-      rtx insn;
+      rtx_insn *insn;
 
       if (!(bb->flags & BB_RTL))
        {
@@ -2733,8 +2773,8 @@ rtl_verify_bb_insn_chain (void)
 {
   basic_block bb;
   int err = 0;
-  rtx x;
-  rtx last_head = get_last_insn ();
+  rtx_insn *x;
+  rtx_insn *last_head = get_last_insn ();
   basic_block *bb_info;
   const int max_uid = get_max_uid ();
 
@@ -2742,8 +2782,8 @@ rtl_verify_bb_insn_chain (void)
 
   FOR_EACH_BB_REVERSE_FN (bb, cfun)
     {
-      rtx head = BB_HEAD (bb);
-      rtx end = BB_END (bb);
+      rtx_insn *head = BB_HEAD (bb);
+      rtx_insn *end = BB_END (bb);
 
       for (x = last_head; x != NULL_RTX; x = PREV_INSN (x))
        {
@@ -2829,7 +2869,7 @@ rtl_verify_fallthru (void)
       e = find_fallthru_edge (bb->succs);
       if (!e)
        {
-         rtx insn;
+         rtx_insn *insn;
 
          /* Ensure existence of barrier in BB with no fallthru edges.  */
          for (insn = NEXT_INSN (BB_END (bb)); ; insn = NEXT_INSN (insn))
@@ -2847,7 +2887,7 @@ rtl_verify_fallthru (void)
       else if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
               && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
        {
-         rtx insn;
+         rtx_insn *insn;
 
          if (e->src->next_bb != e->dest)
            {
@@ -2881,9 +2921,9 @@ rtl_verify_bb_layout (void)
 {
   basic_block bb;
   int err = 0;
-  rtx x;
+  rtx_insn *x;
   int num_bb_notes;
-  const rtx rtx_first = get_insns ();
+  rtx_insn * const rtx_first = get_insns ();
   basic_block last_bb_seen = ENTRY_BLOCK_PTR_FOR_FN (cfun), curr_bb = NULL;
 
   num_bb_notes = 0;
@@ -2980,7 +3020,8 @@ bool
 purge_dead_edges (basic_block bb)
 {
   edge e;
-  rtx insn = BB_END (bb), note;
+  rtx_insn *insn = BB_END (bb);
+  rtx note;
   bool purged = false;
   bool found;
   edge_iterator ei;
@@ -3242,7 +3283,7 @@ fixup_abnormal_edges (void)
 
       if (e && !CALL_P (BB_END (bb)) && !can_throw_internal (BB_END (bb)))
        {
-         rtx insn;
+         rtx_insn *insn;
 
          /* Get past the new insns generated.  Allow notes, as the insns
             may be already deleted.  */
@@ -3254,12 +3295,12 @@ fixup_abnormal_edges (void)
 
          if (CALL_P (insn) || can_throw_internal (insn))
            {
-             rtx stop, next;
+             rtx_insn *stop, *next;
 
              e = find_fallthru_edge (bb->succs);
 
              stop = NEXT_INSN (BB_END (bb));
-             SET_BB_END (bb) = insn;
+             BB_END (bb) = insn;
 
              for (insn = NEXT_INSN (insn); insn != stop; insn = next)
                {
@@ -3276,7 +3317,7 @@ fixup_abnormal_edges (void)
                      if (GET_CODE (PATTERN (insn)) != USE)
                        {
                          /* We're not deleting it, we're moving it.  */
-                         INSN_DELETED_P (insn) = 0;
+                         insn->set_undeleted ();
                          SET_PREV_INSN (insn) = NULL_RTX;
                          SET_NEXT_INSN (insn) = NULL_RTX;
 
@@ -3304,7 +3345,7 @@ fixup_abnormal_edges (void)
 /* Cut the insns from FIRST to LAST out of the insns stream.  */
 
 rtx_insn *
-unlink_insn_chain (rtx first, rtx last)
+unlink_insn_chain (rtx_insn *first, rtx_insn *last)
 {
   rtx_insn *prevfirst = PREV_INSN (first);
   rtx_insn *nextlast = NEXT_INSN (last);
@@ -3319,19 +3360,19 @@ unlink_insn_chain (rtx first, rtx last)
     set_last_insn (prevfirst);
   if (!prevfirst)
     set_first_insn (nextlast);
-  return as_a <rtx_insn *> (first);
+  return first;
 }
 \f
 /* Skip over inter-block insns occurring after BB which are typically
    associated with BB (e.g., barriers). If there are any such insns,
    we return the last one. Otherwise, we return the end of BB.  */
 
-static rtx
+static rtx_insn *
 skip_insns_after_block (basic_block bb)
 {
-  rtx insn, last_insn, next_head, prev;
+  rtx_insn *insn, *last_insn, *next_head, *prev;
 
-  next_head = NULL_RTX;
+  next_head = NULL;
   if (bb->next_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
     next_head = BB_HEAD (bb->next_bb);
 
@@ -3408,10 +3449,10 @@ skip_insns_after_block (basic_block bb)
 
 /* Locate or create a label for a given basic block.  */
 
-static rtx
+static rtx_insn *
 label_for_bb (basic_block bb)
 {
-  rtx label = BB_HEAD (bb);
+  rtx_insn *label = BB_HEAD (bb);
 
   if (!LABEL_P (label))
     {
@@ -3430,9 +3471,9 @@ label_for_bb (basic_block bb)
 static void
 record_effective_endpoints (void)
 {
-  rtx next_insn;
+  rtx_insn *next_insn;
   basic_block bb;
-  rtx insn;
+  rtx_insn *insn;
 
   for (insn = get_insns ();
        insn
@@ -3447,19 +3488,19 @@ record_effective_endpoints (void)
     cfg_layout_function_header =
            unlink_insn_chain (get_insns (), PREV_INSN (insn));
   else
-    cfg_layout_function_header = NULL_RTX;
+    cfg_layout_function_header = NULL;
 
   next_insn = get_insns ();
   FOR_EACH_BB_FN (bb, cfun)
     {
-      rtx end;
+      rtx_insn *end;
 
       if (PREV_INSN (BB_HEAD (bb)) && next_insn != BB_HEAD (bb))
-       SET_BB_HEADER (bb) = unlink_insn_chain (next_insn,
+       BB_HEADER (bb) = unlink_insn_chain (next_insn,
                                                PREV_INSN (BB_HEAD (bb)));
       end = skip_insns_after_block (bb);
       if (NEXT_INSN (BB_END (bb)) && BB_END (bb) != end)
-       SET_BB_FOOTER (bb) = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end);
+       BB_FOOTER (bb) = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end);
       next_insn = NEXT_INSN (BB_END (bb));
     }
 
@@ -3617,7 +3658,7 @@ relink_block_chain (bool stay_in_cfglayout_mode)
     {
       bb->aux = NULL;
       if (!stay_in_cfglayout_mode)
-       SET_BB_HEADER (bb) = SET_BB_FOOTER (bb) = NULL;
+       BB_HEADER (bb) = BB_FOOTER (bb) = NULL;
     }
 
   /* Maybe reset the original copy tables, they are not valid anymore
@@ -3638,7 +3679,7 @@ static void
 fixup_reorder_chain (void)
 {
   basic_block bb;
-  rtx insn = NULL;
+  rtx_insn *insn = NULL;
 
   if (cfg_layout_function_header)
     {
@@ -3699,7 +3740,7 @@ fixup_reorder_chain (void)
        bb->aux)
     {
       edge e_fall, e_taken, e;
-      rtx bb_end_insn;
+      rtx_insn *bb_end_insn;
       rtx ret_label = NULL_RTX;
       basic_block nb;
       edge_iterator ei;
@@ -3718,10 +3759,10 @@ fixup_reorder_chain (void)
          e_taken = e;
 
       bb_end_insn = BB_END (bb);
-      if (JUMP_P (bb_end_insn))
+      if (rtx_jump_insn *bb_end_jump = dyn_cast <rtx_jump_insn *> (bb_end_insn))
        {
-         ret_label = JUMP_LABEL (bb_end_insn);
-         if (any_condjump_p (bb_end_insn))
+         ret_label = JUMP_LABEL (bb_end_jump);
+         if (any_condjump_p (bb_end_jump))
            {
              /* This might happen if the conditional jump has side
                 effects and could therefore not be optimized away.
@@ -3729,10 +3770,10 @@ fixup_reorder_chain (void)
                 to prevent rtl_verify_flow_info from complaining.  */
              if (!e_fall)
                {
-                 gcc_assert (!onlyjump_p (bb_end_insn)
-                             || returnjump_p (bb_end_insn)
+                 gcc_assert (!onlyjump_p (bb_end_jump)
+                             || returnjump_p (bb_end_jump)
                               || (e_taken->flags & EDGE_CROSSING));
-                 emit_barrier_after (bb_end_insn);
+                 emit_barrier_after (bb_end_jump);
                  continue;
                }
 
@@ -3754,11 +3795,11 @@ fixup_reorder_chain (void)
                 edge based on known or assumed probability.  */
              else if (bb->aux != e_taken->dest)
                {
-                 rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
+                 rtx note = find_reg_note (bb_end_jump, REG_BR_PROB, 0);
 
                  if (note
                      && XINT (note, 0) < REG_BR_PROB_BASE / 2
-                     && invert_jump (bb_end_insn,
+                     && invert_jump (bb_end_jump,
                                      (e_fall->dest
                                       == EXIT_BLOCK_PTR_FOR_FN (cfun)
                                       ? NULL_RTX
@@ -3781,7 +3822,7 @@ fixup_reorder_chain (void)
 
              /* Otherwise we can try to invert the jump.  This will
                 basically never fail, however, keep up the pretense.  */
-             else if (invert_jump (bb_end_insn,
+             else if (invert_jump (bb_end_jump,
                                    (e_fall->dest
                                     == EXIT_BLOCK_PTR_FOR_FN (cfun)
                                     ? NULL_RTX
@@ -3875,7 +3916,7 @@ fixup_reorder_chain (void)
              edge e2;
              edge_iterator ei2;
              basic_block dest, nb;
-             rtx end;
+             rtx_insn *end;
 
              insn = BB_END (e->src);
              end = PREV_INSN (BB_HEAD (e->src));
@@ -3910,7 +3951,7 @@ fixup_reorder_chain (void)
                }
              nb = split_edge (e);
              if (!INSN_P (BB_END (nb)))
-               SET_BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb),
+               BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb),
                                                         nb);
              INSN_LOCATION (BB_END (nb)) = e->goto_locus;
 
@@ -3938,7 +3979,7 @@ fixup_reorder_chain (void)
 DEBUG_FUNCTION void
 verify_insn_chain (void)
 {
-  rtx x, prevx, nextx;
+  rtx_insn *x, *prevx, *nextx;
   int insn_cnt1, insn_cnt2;
 
   for (prevx = NULL, insn_cnt1 = 1, x = get_insns ();
@@ -3982,11 +4023,11 @@ fixup_fallthru_exit_predecessor (void)
         edge, we have to split that block.  */
       if (c == bb)
        {
-         bb = split_block (bb, NULL)->dest;
+         bb = split_block_after_labels (bb)->dest;
          bb->aux = c->aux;
          c->aux = bb;
-         SET_BB_FOOTER (bb) = BB_FOOTER (c);
-         SET_BB_FOOTER (c) = NULL;
+         BB_FOOTER (bb) = BB_FOOTER (c);
+         BB_FOOTER (c) = NULL;
        }
 
       while (c->aux != bb)
@@ -4066,7 +4107,7 @@ cfg_layout_can_duplicate_bb_p (const_basic_block bb)
   /* Do not duplicate blocks containing insns that can't be copied.  */
   if (targetm.cannot_copy_insn_p)
     {
-      rtx insn = BB_HEAD (bb);
+      rtx_insn *insn = BB_HEAD (bb);
       while (1)
        {
          if (INSN_P (insn) && targetm.cannot_copy_insn_p (insn))
@@ -4081,9 +4122,9 @@ cfg_layout_can_duplicate_bb_p (const_basic_block bb)
 }
 
 rtx_insn *
-duplicate_insn_chain (rtx from, rtx to)
+duplicate_insn_chain (rtx_insn *from, rtx_insn *to)
 {
-  rtx insn, next, copy;
+  rtx_insn *insn, *next, *copy;
   rtx_note *last;
 
   /* Avoid updating of boundaries of previous basic block.  The
@@ -4152,6 +4193,7 @@ duplicate_insn_chain (rtx from, rtx to)
              break;
 
            case NOTE_INSN_EPILOGUE_BEG:
+           case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
              emit_note_copy (as_a <rtx_note *> (insn));
              break;
 
@@ -4166,7 +4208,7 @@ duplicate_insn_chain (rtx from, rtx to)
     }
   insn = NEXT_INSN (last);
   delete_insn (last);
-  return safe_as_a <rtx_insn *> (insn);
+  return insn;
 }
 
 /* Create a duplicate of the basic block BB.  */
@@ -4174,7 +4216,7 @@ duplicate_insn_chain (rtx from, rtx to)
 static basic_block
 cfg_layout_duplicate_bb (basic_block bb)
 {
-  rtx insn;
+  rtx_insn *insn;
   basic_block new_bb;
 
   insn = duplicate_insn_chain (BB_HEAD (bb), BB_END (bb));
@@ -4190,7 +4232,7 @@ cfg_layout_duplicate_bb (basic_block bb)
        insn = NEXT_INSN (insn);
       insn = duplicate_insn_chain (BB_HEADER (bb), insn);
       if (insn)
-       SET_BB_HEADER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
+       BB_HEADER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
     }
 
   if (BB_FOOTER (bb))
@@ -4200,7 +4242,7 @@ cfg_layout_duplicate_bb (basic_block bb)
        insn = NEXT_INSN (insn);
       insn = duplicate_insn_chain (BB_FOOTER (bb), insn);
       if (insn)
-       SET_BB_FOOTER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
+       BB_FOOTER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
     }
 
   return new_bb;
@@ -4215,7 +4257,7 @@ cfg_layout_duplicate_bb (basic_block bb)
 void
 cfg_layout_initialize (unsigned int flags)
 {
-  rtx x;
+  rtx_insn_list *x;
   basic_block bb;
 
   /* Once bb partitioning is complete, cfg layout mode should not be
@@ -4234,9 +4276,9 @@ cfg_layout_initialize (unsigned int flags)
   record_effective_endpoints ();
 
   /* Make sure that the targets of non local gotos are marked.  */
-  for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
+  for (x = nonlocal_goto_handler_labels; x; x = x->next ())
     {
-      bb = BLOCK_FOR_INSN (XEXP (x, 0));
+      bb = BLOCK_FOR_INSN (x->insn ());
       bb->flags |= BB_NON_LOCAL_GOTO_TARGET;
     }
 
@@ -4282,11 +4324,7 @@ cfg_layout_finalize (void)
 #endif
   force_one_exit_fallthru ();
   rtl_register_cfg_hooks ();
-  if (reload_completed
-#ifdef HAVE_epilogue
-      && !HAVE_epilogue
-#endif
-      )
+  if (reload_completed && !HAVE_epilogue)
     fixup_fallthru_exit_predecessor ();
   fixup_reorder_chain ();
 
@@ -4308,8 +4346,8 @@ cfg_layout_split_block (basic_block bb, void *insnp)
   rtx insn = (rtx) insnp;
   basic_block new_bb = rtl_split_block (bb, insn);
 
-  SET_BB_FOOTER (new_bb) = BB_FOOTER (bb);
-  SET_BB_FOOTER (bb) = NULL;
+  BB_FOOTER (new_bb) = BB_FOOTER (bb);
+  BB_FOOTER (bb) = NULL;
 
   return new_bb;
 }
@@ -4412,7 +4450,8 @@ cfg_layout_redirect_edge_and_branch_force (edge e, basic_block dest)
 static void
 cfg_layout_delete_block (basic_block bb)
 {
-  rtx insn, next, prev = PREV_INSN (BB_HEAD (bb)), *to, remaints;
+  rtx_insn *insn, *next, *prev = PREV_INSN (BB_HEAD (bb)), *remaints;
+  rtx_insn **to;
 
   if (BB_HEADER (bb))
     {
@@ -4439,7 +4478,7 @@ cfg_layout_delete_block (basic_block bb)
              if (PREV_INSN (insn))
                SET_NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
              else
-               SET_BB_FOOTER (bb) = NEXT_INSN (insn);
+               BB_FOOTER (bb) = NEXT_INSN (insn);
              if (NEXT_INSN (insn))
                SET_PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
            }
@@ -4462,7 +4501,7 @@ cfg_layout_delete_block (basic_block bb)
        }
     }
   if (bb->next_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
-    to = &SET_BB_HEADER (bb->next_bb);
+    to = &BB_HEADER (bb->next_bb);
   else
     to = &cfg_layout_function_footer;
 
@@ -4545,7 +4584,7 @@ static void
 cfg_layout_merge_blocks (basic_block a, basic_block b)
 {
   bool forwarder_p = (b->flags & BB_FORWARDER_BLOCK) != 0;
-  rtx insn;
+  rtx_insn *insn;
 
   gcc_checking_assert (cfg_layout_can_merge_blocks_p (a, b));
 
@@ -4574,17 +4613,17 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
   if (BB_FOOTER (b))
     {
       if (!BB_FOOTER (a))
-       SET_BB_FOOTER (a) = SET_BB_FOOTER (b);
+       BB_FOOTER (a) = BB_FOOTER (b);
       else
        {
-         rtx last = BB_FOOTER (a);
+         rtx_insn *last = BB_FOOTER (a);
 
          while (NEXT_INSN (last))
            last = NEXT_INSN (last);
          SET_NEXT_INSN (last) = BB_FOOTER (b);
          SET_PREV_INSN (BB_FOOTER (b)) = last;
        }
-      SET_BB_FOOTER (b) = NULL;
+      BB_FOOTER (b) = NULL;
     }
 
   /* Move things from b->header before a->footer.
@@ -4593,18 +4632,18 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
    if (BB_HEADER (b))
      {
       if (! BB_FOOTER (a))
-       SET_BB_FOOTER (a) = BB_HEADER (b);
+       BB_FOOTER (a) = BB_HEADER (b);
       else
        {
-         rtx last = BB_HEADER (b);
+         rtx_insn *last = BB_HEADER (b);
  
          while (NEXT_INSN (last))
            last = NEXT_INSN (last);
          SET_NEXT_INSN (last) = BB_FOOTER (a);
          SET_PREV_INSN (BB_FOOTER (a)) = last;
-         SET_BB_FOOTER (a) = BB_HEADER (b);
+         BB_FOOTER (a) = BB_HEADER (b);
        }
-      SET_BB_HEADER (b) = NULL;
+      BB_HEADER (b) = NULL;
     }
 
   /* In the case basic blocks are not adjacent, move them around.  */
@@ -4618,7 +4657,7 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
   else
     {
       insn = BB_HEAD (b);
-      SET_BB_END (a) = BB_END (b);
+      BB_END (a) = BB_END (b);
     }
 
   /* emit_insn_after_noloc doesn't call df_insn_change_bb.
@@ -4629,7 +4668,7 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
   if (!NOTE_INSN_BASIC_BLOCK_P (insn))
     insn = NEXT_INSN (insn);
   gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn));
-  SET_BB_HEAD (b) = SET_BB_END (b) = NULL;
+  BB_HEAD (b) = BB_END (b) = NULL;
   delete_insn (insn);
 
   df_bb_delete (b->index);
@@ -4676,7 +4715,7 @@ rtl_make_forwarder_block (edge fallthru ATTRIBUTE_UNUSED)
 static bool
 rtl_block_empty_p (basic_block bb)
 {
-  rtx insn;
+  rtx_insn *insn;
 
   if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)
       || bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
@@ -4695,9 +4734,9 @@ rtl_block_empty_p (basic_block bb)
 static basic_block
 rtl_split_block_before_cond_jump (basic_block bb)
 {
-  rtx insn;
-  rtx split_point = NULL;
-  rtx last = NULL;
+  rtx_insn *insn;
+  rtx_insn *split_point = NULL;
+  rtx_insn *last = NULL;
   bool found_code = false;
 
   FOR_BB_INSNS (bb, insn)
@@ -4722,7 +4761,7 @@ rtl_split_block_before_cond_jump (basic_block bb)
 static bool
 rtl_block_ends_with_call_p (basic_block bb)
 {
-  rtx insn = BB_END (bb);
+  rtx_insn *insn = BB_END (bb);
 
   while (!CALL_P (insn)
         && insn != BB_HEAD (bb)
@@ -4745,7 +4784,7 @@ rtl_block_ends_with_condjump_p (const_basic_block bb)
    Helper function for rtl_flow_call_edges_add.  */
 
 static bool
-need_fake_edge_p (const_rtx insn)
+need_fake_edge_p (const rtx_insn *insn)
 {
   if (!INSN_P (insn))
     return false;
@@ -4804,7 +4843,7 @@ rtl_flow_call_edges_add (sbitmap blocks)
   if (check_last_block)
     {
       basic_block bb = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
-      rtx insn = BB_END (bb);
+      rtx_insn *insn = BB_END (bb);
 
       /* Back up past insns that must be kept in the same block as a call.  */
       while (insn != BB_HEAD (bb)
@@ -4831,8 +4870,8 @@ rtl_flow_call_edges_add (sbitmap blocks)
   for (i = NUM_FIXED_BLOCKS; i < last_bb; i++)
     {
       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
-      rtx insn;
-      rtx prev_insn;
+      rtx_insn *insn;
+      rtx_insn *prev_insn;
 
       if (!bb)
        continue;
@@ -4846,7 +4885,7 @@ rtl_flow_call_edges_add (sbitmap blocks)
          if (need_fake_edge_p (insn))
            {
              edge e;
-             rtx split_at_insn = insn;
+             rtx_insn *split_at_insn = insn;
 
              /* Don't split the block between a call and an insn that should
                 remain in the same block as the call.  */
@@ -4901,11 +4940,12 @@ rtl_lv_add_condition_to_bb (basic_block first_head ,
                            basic_block second_head ATTRIBUTE_UNUSED,
                            basic_block cond_bb, void *comp_rtx)
 {
-  rtx label, seq, jump;
+  rtx_code_label *label;
+  rtx_insn *seq, *jump;
   rtx op0 = XEXP ((rtx)comp_rtx, 0);
   rtx op1 = XEXP ((rtx)comp_rtx, 1);
   enum rtx_code comp = GET_CODE ((rtx)comp_rtx);
-  enum machine_mode mode;
+  machine_mode mode;
 
 
   label = block_label (first_head);
@@ -4916,15 +4956,14 @@ rtl_lv_add_condition_to_bb (basic_block first_head ,
   start_sequence ();
   op0 = force_operand (op0, NULL_RTX);
   op1 = force_operand (op1, NULL_RTX);
-  do_compare_rtx_and_jump (op0, op1, comp, 0,
-                          mode, NULL_RTX, NULL_RTX, label, -1);
+  do_compare_rtx_and_jump (op0, op1, comp, 0, mode, NULL_RTX, NULL, label, -1);
   jump = get_last_insn ();
   JUMP_LABEL (jump) = label;
   LABEL_NUSES (label)++;
   seq = get_insns ();
   end_sequence ();
 
-  /* Add the new cond , in the new head.  */
+  /* Add the new cond, in the new head.  */
   emit_insn_after (seq, BB_END (cond_bb));
 }
 
@@ -4966,7 +5005,8 @@ rtl_can_remove_branch_p (const_edge e)
 {
   const_basic_block src = e->src;
   const_basic_block target = EDGE_SUCC (src, EDGE_SUCC (src, 0) == e)->dest;
-  const_rtx insn = BB_END (src), set;
+  const rtx_insn *insn = BB_END (src);
+  rtx set;
 
   /* The conditions are taken from try_redirect_by_replacing_jump.  */
   if (target == EXIT_BLOCK_PTR_FOR_FN (cfun))
@@ -5004,7 +5044,7 @@ static void
 rtl_account_profile_record (basic_block bb, int after_pass,
                            struct profile_record *record)
 {
-  rtx insn;
+  rtx_insn *insn;
   FOR_BB_INSNS (bb, insn)
     if (INSN_P (insn))
       {
@@ -5099,64 +5139,4 @@ struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
   rtl_account_profile_record,
 };
 
-/* BB_HEAD as an rvalue. */
-
-rtx_insn *BB_HEAD (const_basic_block bb)
-{
-  rtx insn = bb->il.x.head_;
-  return safe_as_a <rtx_insn *> (insn);
-}
-
-/* BB_HEAD for use as an lvalue. */
-
-rtx& SET_BB_HEAD (basic_block bb)
-{
-  return bb->il.x.head_;
-}
-
-/* BB_END as an rvalue. */
-
-rtx_insn *BB_END (const_basic_block bb)
-{
-  rtx insn = bb->il.x.rtl->end_;
-  return safe_as_a <rtx_insn *> (insn);
-}
-
-/* BB_END as an lvalue. */
-
-rtx& SET_BB_END (basic_block bb)
-{
-  return bb->il.x.rtl->end_;
-}
-
-/* BB_HEADER as an rvalue. */
-
-rtx_insn *BB_HEADER (const_basic_block bb)
-{
-  rtx insn = bb->il.x.rtl->header_;
-  return safe_as_a <rtx_insn *> (insn);
-}
-
-/* BB_HEADER as an lvalue. */
-
-rtx& SET_BB_HEADER (basic_block bb)
-{
-  return bb->il.x.rtl->header_;
-}
-
-/* BB_FOOTER as an rvalue. */
-
-rtx_insn *BB_FOOTER (const_basic_block bb)
-{
-  rtx insn = bb->il.x.rtl->footer_;
-  return safe_as_a <rtx_insn *> (insn);
-}
-
-/* BB_FOOTER as an lvalue. */
-
-rtx& SET_BB_FOOTER (basic_block bb)
-{
-  return bb->il.x.rtl->footer_;
-}
-
 #include "gt-cfgrtl.h"