OSDN Git Service

* config/arm/arm.c (arm_init_libfuncs): Clear mod optabs.
[pf3gnuchains/gcc-fork.git] / gcc / final.c
index 1938604..7d78061 100644 (file)
@@ -1,6 +1,7 @@
 /* Convert RTL to assembler code and output it, for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -111,6 +112,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define HAVE_READONLY_DATA_SECTION 0
 #endif
 
+/* Bitflags used by final_scan_insn.  */
+#define SEEN_BB                1
+#define SEEN_NOTE      2
+#define SEEN_EMITTED   4
+
 /* Last insn processed by final_scan_insn.  */
 static rtx debug_insn;
 rtx current_output_insn;
@@ -170,9 +176,15 @@ CC_STATUS cc_prev_status;
 
 char regs_ever_live[FIRST_PSEUDO_REGISTER];
 
+/* Like regs_ever_live, but 1 if a reg is set or clobbered from an asm.
+   Unlike regs_ever_live, elements of this array corresponding to
+   eliminable regs like the frame pointer are set if an asm sets them.  */
+
+char regs_asm_clobbered[FIRST_PSEUDO_REGISTER];
+
 /* Nonzero means current function must be given a frame pointer.
-   Set in stmt.c if anything is allocated on the stack there.
-   Set in reload1.c if anything is allocated on the stack there.  */
+   Initialized in function.c to 0.  Set only in reload1.c as per
+   the needs of the function.  */
 
 int frame_pointer_needed;
 
@@ -195,10 +207,6 @@ rtx final_sequence;
 static int dialect_number;
 #endif
 
-/* Indexed by line number, nonzero if there is a note for that line.  */
-
-static char *line_note_exists;
-
 #ifdef HAVE_conditional_execution
 /* Nonnull if the insn currently being emitted was a COND_EXEC pattern.  */
 rtx current_insn_predicate;
@@ -618,7 +626,7 @@ insn_current_reference_address (rtx branch)
 
   seq = NEXT_INSN (PREV_INSN (branch));
   seq_uid = INSN_UID (seq);
-  if (GET_CODE (branch) != JUMP_INSN)
+  if (!JUMP_P (branch))
     /* This can happen for example on the PA; the objective is to know the
        offset to address something in front of the start of the function.
        Thus, we can treat it like a backward branch.
@@ -667,17 +675,18 @@ compute_alignments (void)
 
   FOR_EACH_BB (bb)
     {
-      rtx label = bb->head;
+      rtx label = BB_HEAD (bb);
       int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0;
       edge e;
+      edge_iterator ei;
 
-      if (GET_CODE (label) != CODE_LABEL
+      if (!LABEL_P (label)
          || probably_never_executed_bb_p (bb))
        continue;
       max_log = LABEL_ALIGN (label);
       max_skip = LABEL_ALIGN_MAX_SKIP;
 
-      for (e = bb->pred; e; e = e->pred_next)
+      FOR_EACH_EDGE (e, ei, bb->preds)
        {
          if (e->flags & EDGE_FALLTHRU)
            has_fallthru = 1, fallthru_frequency += EDGE_FREQUENCY (e);
@@ -730,12 +739,6 @@ compute_alignments (void)
 /* Make a pass over all insns and compute their actual lengths by shortening
    any branches of variable length if possible.  */
 
-/* Give a default value for the lowest address in a function.  */
-
-#ifndef FIRST_INSN_ADDRESS
-#define FIRST_INSN_ADDRESS 0
-#endif
-
 /* shorten_branches might be called multiple times:  for example, the SH
    port splits out-of-range conditional branches in MACHINE_DEPENDENT_REORG.
    In order to do this, it needs proper length information, which it obtains
@@ -766,6 +769,9 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
   /* Compute maximum UID and allocate label_align / uid_shuid.  */
   max_uid = get_max_uid ();
 
+  /* Free uid_shuid before reallocating it.  */
+  free (uid_shuid);
+  
   uid_shuid = xmalloc (max_uid * sizeof *uid_shuid);
 
   if (max_labelno != max_label_num ())
@@ -784,8 +790,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
 
       /* Range of labels grows monotonically in the function.  Abort here
          means that the initialization of array got lost.  */
-      if (n_old_labels > n_labels)
-       abort ();
+      gcc_assert (n_old_labels <= n_labels);
 
       memset (label_align + n_old_labels, 0,
              (n_labels - n_old_labels) * sizeof (struct label_alignment));
@@ -813,7 +818,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
              is separated by the former loop start insn from the
             NOTE_INSN_LOOP_BEG.  */
        }
-      else if (GET_CODE (insn) == CODE_LABEL)
+      else if (LABEL_P (insn))
        {
          rtx next;
 
@@ -831,11 +836,11 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
              max_log = log;
              max_skip = LABEL_ALIGN_MAX_SKIP;
            }
-         next = NEXT_INSN (insn);
+         next = next_nonnote_insn (insn);
          /* ADDR_VECs only take room if read-only data goes into the text
             section.  */
          if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
-           if (next && GET_CODE (next) == JUMP_INSN)
+           if (next && JUMP_P (next))
              {
                rtx nextbody = PATTERN (next);
                if (GET_CODE (nextbody) == ADDR_VEC
@@ -854,13 +859,13 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
          max_log = 0;
          max_skip = 0;
        }
-      else if (GET_CODE (insn) == BARRIER)
+      else if (BARRIER_P (insn))
        {
          rtx label;
 
          for (label = insn; label && ! INSN_P (label);
               label = NEXT_INSN (label))
-           if (GET_CODE (label) == CODE_LABEL)
+           if (LABEL_P (label))
              {
                log = LABEL_ALIGN_AFTER_BARRIER (insn);
                if (max_log < log)
@@ -897,7 +902,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
     {
       int uid = INSN_UID (seq);
       int log;
-      log = (GET_CODE (seq) == CODE_LABEL ? LABEL_TO_ALIGNMENT (seq) : 0);
+      log = (LABEL_P (seq) ? LABEL_TO_ALIGNMENT (seq) : 0);
       uid_align[uid] = align_tab[0];
       if (log)
        {
@@ -924,13 +929,12 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
          int min_align;
          addr_diff_vec_flags flags;
 
-         if (GET_CODE (insn) != JUMP_INSN
+         if (!JUMP_P (insn)
              || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
            continue;
          pat = PATTERN (insn);
          len = XVECLEN (pat, 1);
-         if (len <= 0)
-           abort ();
+         gcc_assert (len > 0);
          min_align = MAX_CODE_ALIGN;
          for (min = max_shuid, max = min_shuid, i = len - 1; i >= 0; i--)
            {
@@ -953,6 +957,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
          XEXP (pat, 3) = gen_rtx_LABEL_REF (VOIDmode, max_lab);
          insn_shuid = INSN_SHUID (insn);
          rel = INSN_SHUID (XEXP (XEXP (pat, 0), 0));
+         memset (&flags, 0, sizeof (flags));
          flags.min_align = min_align;
          flags.base_after_vec = rel > insn_shuid;
          flags.min_after_vec  = min > insn_shuid;
@@ -965,7 +970,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
 #endif /* CASE_VECTOR_SHORTEN_MODE */
 
   /* Compute initial lengths, addresses, and varying flags for each insn.  */
-  for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;
+  for (insn_current_address = 0, insn = first;
        insn != 0;
        insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
     {
@@ -973,7 +978,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
 
       insn_lengths[uid] = 0;
 
-      if (GET_CODE (insn) == CODE_LABEL)
+      if (LABEL_P (insn))
        {
          int log = LABEL_TO_ALIGNMENT (insn);
          if (log)
@@ -986,8 +991,8 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
 
       INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
 
-      if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER
-         || GET_CODE (insn) == CODE_LABEL)
+      if (NOTE_P (insn) || BARRIER_P (insn)
+         || LABEL_P (insn))
        continue;
       if (INSN_DELETED_P (insn))
        continue;
@@ -1066,7 +1071,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
     {
       something_changed = 0;
       insn_current_align = MAX_CODE_ALIGN - 1;
-      for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;
+      for (insn_current_address = 0, insn = first;
           insn != 0;
           insn = NEXT_INSN (insn))
        {
@@ -1078,7 +1083,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
 
          uid = INSN_UID (insn);
 
-         if (GET_CODE (insn) == CODE_LABEL)
+         if (LABEL_P (insn))
            {
              int log = LABEL_TO_ALIGNMENT (insn);
              if (log > insn_current_align)
@@ -1103,7 +1108,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
          INSN_ADDRESSES (uid) = insn_current_address;
 
 #ifdef CASE_VECTOR_SHORTEN_MODE
-         if (optimize && GET_CODE (insn) == JUMP_INSN
+         if (optimize && JUMP_P (insn)
              && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
            {
              rtx body = PATTERN (insn);
@@ -1213,7 +1218,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
 
          if (! (varying_length[uid]))
            {
-             if (GET_CODE (insn) == INSN
+             if (NONJUMP_INSN_P (insn)
                  && GET_CODE (PATTERN (insn)) == SEQUENCE)
                {
                  int i;
@@ -1235,7 +1240,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
              continue;
            }
 
-         if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
+         if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
            {
              int i;
 
@@ -1336,19 +1341,6 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
 
   this_is_asm_operands = 0;
 
-#ifdef NON_SAVING_SETJMP
-  /* A function that calls setjmp should save and restore all the
-     call-saved registers on a system where longjmp clobbers them.  */
-  if (NON_SAVING_SETJMP && current_function_calls_setjmp)
-    {
-      int i;
-
-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-       if (!call_used_regs[i])
-         regs_ever_live[i] = 1;
-    }
-#endif
-
   last_filename = locator_file (prologue_locator);
   last_linenum = locator_line (prologue_locator);
 
@@ -1356,7 +1348,7 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
 
   (*debug_hooks->begin_prologue) (last_linenum, last_filename);
 
-#if defined (DWARF2_UNWIND_INFO) || defined (IA64_UNWIND_INFO)
+#if defined (DWARF2_UNWIND_INFO) || defined (TARGET_UNWIND_INFO)
   if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG)
     dwarf2out_begin_prologue (0, NULL);
 #endif
@@ -1375,7 +1367,7 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
 
 #if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue)
   if (dwarf2out_do_frame ())
-    dwarf2out_frame_debug (NULL_RTX);
+    dwarf2out_frame_debug (NULL_RTX, false);
 #endif
 
   /* If debugging, assign block numbers to all of the blocks in this
@@ -1392,7 +1384,7 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
     }
 
   /* First output the function prologue: code to set up the stack frame.  */
-  (*targetm.asm_out.function_prologue) (file, get_frame_size ());
+  targetm.asm_out.function_prologue (file, get_frame_size ());
 
   /* If the machine represents the prologue as RTL, the profiling code must
      be emitted when NOTE_INSN_PROLOGUE_END is scanned.  */
@@ -1421,7 +1413,7 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
   int sval = current_function_returns_struct;
   rtx svrtx = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), 1);
 #if defined(STATIC_CHAIN_INCOMING_REGNUM) || defined(STATIC_CHAIN_REGNUM)
-  int cxt = current_function_needs_context;
+  int cxt = cfun->static_chain_decl != NULL;
 #endif
 #endif /* ASM_OUTPUT_REG_PUSH */
 
@@ -1430,14 +1422,14 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
       int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
       data_section ();
       ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
-      (*targetm.asm_out.internal_label) (file, "LP", current_function_funcdef_no);
+      targetm.asm_out.internal_label (file, "LP", current_function_funcdef_no);
       assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
     }
 
-  function_section (current_function_decl);
+  current_function_section (current_function_decl);
 
 #if defined(ASM_OUTPUT_REG_PUSH)
-  if (sval && GET_CODE (svrtx) == REG)
+  if (sval && svrtx != NULL_RTX && REG_P (svrtx))
     ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx));
 #endif
 
@@ -1468,7 +1460,7 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
 #endif
 
 #if defined(ASM_OUTPUT_REG_PUSH)
-  if (sval && GET_CODE (svrtx) == REG)
+  if (sval && svrtx != NULL_RTX && REG_P (svrtx))
     ASM_OUTPUT_REG_POP (file, REGNO (svrtx));
 #endif
 }
@@ -1486,7 +1478,7 @@ final_end_function (void)
 
   /* Finally, output the function epilogue:
      code to restore the stack frame and return to the caller.  */
-  (*targetm.asm_out.function_epilogue) (asm_out_file, get_frame_size ());
+  targetm.asm_out.function_epilogue (asm_out_file, get_frame_size ());
 
   /* And debug output.  */
   (*debug_hooks->end_epilogue) (last_linenum, last_filename);
@@ -1499,70 +1491,52 @@ final_end_function (void)
 }
 \f
 /* Output assembler code for some insns: all or part of a function.
-   For description of args, see `final_start_function', above.
-
-   PRESCAN is 1 if we are not really outputting,
-     just scanning as if we were outputting.
-   Prescanning deletes and rearranges insns just like ordinary output.
-   PRESCAN is -2 if we are outputting after having prescanned.
-   In this case, don't try to delete or rearrange insns
-   because that has already been done.
-   Prescanning is done only on certain machines.  */
+   For description of args, see `final_start_function', above.  */
 
 void
-final (rtx first, FILE *file, int optimize, int prescan)
+final (rtx first, FILE *file, int optimize)
 {
   rtx insn;
-  int max_line = 0;
   int max_uid = 0;
+  int seen = 0;
 
   last_ignored_compare = 0;
 
-  /* Make a map indicating which line numbers appear in this function.
-     When producing SDB debugging info, delete troublesome line number
+#ifdef SDB_DEBUGGING_INFO
+  /* When producing SDB debugging info, delete troublesome line number
      notes from inlined functions in other files as well as duplicate
      line number notes.  */
-#ifdef SDB_DEBUGGING_INFO
   if (write_symbols == SDB_DEBUG)
     {
       rtx last = 0;
       for (insn = first; insn; insn = NEXT_INSN (insn))
-       if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
+       if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0)
          {
-           if ((RTX_INTEGRATED_P (insn)
-                && strcmp (NOTE_SOURCE_FILE (insn), main_input_filename) != 0)
-                || (last != 0
-                    && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last)
-                    && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last)))
+           if (last != 0
+#ifdef USE_MAPPED_LOCATION
+               && NOTE_SOURCE_LOCATION (insn) == NOTE_SOURCE_LOCATION (last)
+#else
+               && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last)
+               && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last)
+#endif
+             )
              {
                delete_insn (insn);     /* Use delete_note.  */
                continue;
              }
            last = insn;
-           if (NOTE_LINE_NUMBER (insn) > max_line)
-             max_line = NOTE_LINE_NUMBER (insn);
          }
     }
-  else
 #endif
-    {
-      for (insn = first; insn; insn = NEXT_INSN (insn))
-       if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > max_line)
-         max_line = NOTE_LINE_NUMBER (insn);
-    }
-
-  line_note_exists = xcalloc (max_line + 1, sizeof (char));
 
   for (insn = first; insn; insn = NEXT_INSN (insn))
     {
       if (INSN_UID (insn) > max_uid)       /* Find largest UID.  */
        max_uid = INSN_UID (insn);
-      if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
-       line_note_exists[NOTE_LINE_NUMBER (insn)] = 1;
 #ifdef HAVE_cc0
       /* If CC tracking across branches is enabled, record the insn which
         jumps to each branch only reached from one place.  */
-      if (optimize && GET_CODE (insn) == JUMP_INSN)
+      if (optimize && JUMP_P (insn))
        {
          rtx lab = JUMP_LABEL (insn);
          if (lab && LABEL_NUSES (lab) == 1)
@@ -1585,39 +1559,32 @@ final (rtx first, FILE *file, int optimize, int prescan)
        {
          /* This can be triggered by bugs elsewhere in the compiler if
             new insns are created after init_insn_lengths is called.  */
-         if (GET_CODE (insn) == NOTE)
-           insn_current_address = -1;
-         else
-           abort ();
+         gcc_assert (NOTE_P (insn));
+         insn_current_address = -1;
        }
       else
        insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
 #endif /* HAVE_ATTR_length */
 
-      insn = final_scan_insn (insn, file, optimize, prescan, 0);
+      insn = final_scan_insn (insn, file, optimize, 0, &seen);
     }
-
-  free (line_note_exists);
-  line_note_exists = NULL;
 }
 \f
 const char *
 get_insn_template (int code, rtx insn)
 {
-  const void *output = insn_data[code].output;
   switch (insn_data[code].output_format)
     {
     case INSN_OUTPUT_FORMAT_SINGLE:
-      return (const char *) output;
+      return insn_data[code].output.single;
     case INSN_OUTPUT_FORMAT_MULTI:
-      return ((const char *const *) output)[which_alternative];
+      return insn_data[code].output.multi[which_alternative];
     case INSN_OUTPUT_FORMAT_FUNCTION:
-      if (insn == NULL)
-       abort ();
-      return (*(insn_output_fn) output) (recog_data.operand, insn);
+      gcc_assert (insn);
+      return (*insn_data[code].output.function) (recog_data.operand, insn);
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -1638,7 +1605,7 @@ output_alternate_entry_point (FILE *file, rtx insn)
       ASM_WEAKEN_LABEL (file, name);
 #endif
     case LABEL_GLOBAL_ENTRY:
-      (*targetm.asm_out.globalize_label) (file, name);
+      targetm.asm_out.globalize_label (file, name);
     case LABEL_STATIC_ENTRY:
 #ifdef ASM_OUTPUT_TYPE_DIRECTIVE
       ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
@@ -1648,7 +1615,7 @@ output_alternate_entry_point (FILE *file, rtx insn)
 
     case LABEL_NORMAL:
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -1658,15 +1625,22 @@ output_alternate_entry_point (FILE *file, rtx insn)
    Value returned is the next insn to be scanned.
 
    NOPEEPHOLES is the flag to disallow peephole processing (currently
-   used for within delayed branch sequence output).  */
+   used for within delayed branch sequence output).
+
+   SEEN is used to track the end of the prologue, for emitting
+   debug information.  We force the emission of a line note after
+   both NOTE_INSN_PROLOGUE_END and NOTE_INSN_FUNCTION_BEG, or
+   at the beginning of the second basic block, whichever comes
+   first.  */
 
 rtx
 final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
-                int prescan, int nopeepholes ATTRIBUTE_UNUSED)
+                int nopeepholes ATTRIBUTE_UNUSED, int *seen)
 {
 #ifdef HAVE_cc0
   rtx set;
 #endif
+  rtx next;
 
   insn_counter++;
 
@@ -1678,29 +1652,53 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
   switch (GET_CODE (insn))
     {
     case NOTE:
-      if (prescan > 0)
-       break;
-
       switch (NOTE_LINE_NUMBER (insn))
        {
        case NOTE_INSN_DELETED:
        case NOTE_INSN_LOOP_BEG:
        case NOTE_INSN_LOOP_END:
-       case NOTE_INSN_LOOP_END_TOP_COND:
-       case NOTE_INSN_LOOP_CONT:
-       case NOTE_INSN_LOOP_VTOP:
        case NOTE_INSN_FUNCTION_END:
        case NOTE_INSN_REPEATED_LINE_NUMBER:
        case NOTE_INSN_EXPECTED_VALUE:
          break;
 
+       case NOTE_INSN_SWITCH_TEXT_SECTIONS:
+         
+         /* The presence of this note indicates that this basic block
+            belongs in the "cold" section of the .o file.  If we are
+            not already writing to the cold section we need to change
+            to it.  */
+
+         if (last_text_section == in_text)
+           {
+             (*debug_hooks->switch_text_section) ();
+             unlikely_text_section ();
+           }
+         else
+           {
+             (*debug_hooks->switch_text_section) ();
+             text_section ();
+           }
+         break;
+         
        case NOTE_INSN_BASIC_BLOCK:
-#ifdef IA64_UNWIND_INFO
-         IA64_UNWIND_EMIT (asm_out_file, insn);
+         
+#ifdef TARGET_UNWIND_INFO
+         targetm.asm_out.unwind_emit (asm_out_file, insn);
 #endif
+
          if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s basic block %d\n",
                     ASM_COMMENT_START, NOTE_BASIC_BLOCK (insn)->index);
+
+         if ((*seen & (SEEN_EMITTED | SEEN_BB)) == SEEN_BB)
+           {
+             *seen |= SEEN_EMITTED;
+             last_filename = NULL;
+           }
+         else
+           *seen |= SEEN_BB;
+
          break;
 
        case NOTE_INSN_EH_REGION_BEG:
@@ -1714,23 +1712,40 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
          break;
 
        case NOTE_INSN_PROLOGUE_END:
-         (*targetm.asm_out.function_end_prologue) (file);
+         targetm.asm_out.function_end_prologue (file);
          profile_after_prologue (file);
+
+         if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
+           {
+             *seen |= SEEN_EMITTED;
+             last_filename = NULL;
+           }
+         else
+           *seen |= SEEN_NOTE;
+
          break;
 
        case NOTE_INSN_EPILOGUE_BEG:
-         (*targetm.asm_out.function_begin_epilogue) (file);
+         targetm.asm_out.function_begin_epilogue (file);
          break;
 
        case NOTE_INSN_FUNCTION_BEG:
          app_disable ();
          (*debug_hooks->end_prologue) (last_linenum, last_filename);
+
+         if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
+           {
+             *seen |= SEEN_EMITTED;
+             last_filename = NULL;
+           }
+         else
+           *seen |= SEEN_NOTE;
+
          break;
 
        case NOTE_INSN_BLOCK_BEG:
          if (debug_info_level == DINFO_LEVEL_NORMAL
              || debug_info_level == DINFO_LEVEL_VERBOSE
-             || write_symbols == DWARF_DEBUG
              || write_symbols == DWARF2_DEBUG
              || write_symbols == VMS_AND_DWARF2_DEBUG
              || write_symbols == VMS_DEBUG)
@@ -1752,7 +1767,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
        case NOTE_INSN_BLOCK_END:
          if (debug_info_level == DINFO_LEVEL_NORMAL
              || debug_info_level == DINFO_LEVEL_VERBOSE
-             || write_symbols == DWARF_DEBUG
              || write_symbols == DWARF2_DEBUG
              || write_symbols == VMS_AND_DWARF2_DEBUG
              || write_symbols == VMS_DEBUG)
@@ -1763,8 +1777,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
 
              /* End of a symbol-block.  */
              --block_depth;
-             if (block_depth < 0)
-               abort ();
+             gcc_assert (block_depth >= 0);
 
              (*debug_hooks->end_block) (high_block_linenum, n);
            }
@@ -1777,12 +1790,15 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
          ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
          break;
 
+       case NOTE_INSN_VAR_LOCATION:
+         (*debug_hooks->var_location) (insn);
+         break;
+
        case 0:
          break;
 
        default:
-         if (NOTE_LINE_NUMBER (insn) <= 0)
-           abort ();
+         gcc_assert (NOTE_LINE_NUMBER (insn) > 0);
          break;
        }
       break;
@@ -1790,7 +1806,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
     case BARRIER:
 #if defined (DWARF2_UNWIND_INFO)
       if (dwarf2out_do_frame ())
-       dwarf2out_frame_debug (insn);
+       dwarf2out_frame_debug (insn, false);
 #endif
       break;
 
@@ -1834,22 +1850,16 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
             insn, and that branch is the only way to reach this label,
             set the condition codes based on the branch and its
             predecessor.  */
-         if (barrier && GET_CODE (barrier) == BARRIER
-             && jump && GET_CODE (jump) == JUMP_INSN
+         if (barrier && BARRIER_P (barrier)
+             && jump && JUMP_P (jump)
              && (prev = prev_nonnote_insn (jump))
-             && GET_CODE (prev) == INSN)
+             && NONJUMP_INSN_P (prev))
            {
              NOTICE_UPDATE_CC (PATTERN (prev), prev);
              NOTICE_UPDATE_CC (PATTERN (jump), jump);
            }
        }
 #endif
-      if (prescan > 0)
-       break;
-
-#ifdef FINAL_PRESCAN_LABEL
-      FINAL_PRESCAN_INSN (insn, NULL, 0);
-#endif
 
       if (LABEL_NAME (insn))
        (*debug_hooks->label) (insn);
@@ -1859,10 +1869,11 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
          fputs (ASM_APP_OFF, file);
          app_on = 0;
        }
-      if (NEXT_INSN (insn) != 0
-         && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN)
+
+      next = next_nonnote_insn (insn);
+      if (next != 0 && JUMP_P (next))
        {
-         rtx nextbody = PATTERN (NEXT_INSN (insn));
+         rtx nextbody = PATTERN (next);
 
          /* If this label is followed by a jump-table,
             make sure we put the label in the read-only section.  Also
@@ -1880,23 +1891,23 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
                {
                  int log_align;
 
-                 readonly_data_section ();
+                 targetm.asm_out.function_rodata_section (current_function_decl);
 
 #ifdef ADDR_VEC_ALIGN
-                 log_align = ADDR_VEC_ALIGN (NEXT_INSN (insn));
+                 log_align = ADDR_VEC_ALIGN (next);
 #else
                  log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
 #endif
                  ASM_OUTPUT_ALIGN (file, log_align);
                }
              else
-               function_section (current_function_decl);
+               current_function_section (current_function_decl);
 
 #ifdef ASM_OUTPUT_CASE_LABEL
              ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
-                                    NEXT_INSN (insn));
+                                    next);
 #else
-             (*targetm.asm_out.internal_label) (file, "L", CODE_LABEL_NUMBER (insn));
+             targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
 #endif
 #endif
              break;
@@ -1905,7 +1916,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
       if (LABEL_ALT_ENTRY_P (insn))
        output_alternate_entry_point (file, insn);
       else
-       (*targetm.asm_out.internal_label) (file, "L", CODE_LABEL_NUMBER (insn));
+       targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
       break;
 
     default:
@@ -1913,27 +1924,28 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
        rtx body = PATTERN (insn);
        int insn_code_number;
        const char *template;
-       rtx note;
 
        /* An INSN, JUMP_INSN or CALL_INSN.
           First check for special kinds that recog doesn't recognize.  */
 
-       if (GET_CODE (body) == USE /* These are just declarations */
+       if (GET_CODE (body) == USE /* These are just declarations */
            || GET_CODE (body) == CLOBBER)
          break;
 
 #ifdef HAVE_cc0
-       /* If there is a REG_CC_SETTER note on this insn, it means that
-          the setting of the condition code was done in the delay slot
-          of the insn that branched here.  So recover the cc status
-          from the insn that set it.  */
+       {
+         /* If there is a REG_CC_SETTER note on this insn, it means that
+            the setting of the condition code was done in the delay slot
+            of the insn that branched here.  So recover the cc status
+            from the insn that set it.  */
 
-       note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
-       if (note)
-         {
-           NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));
-           cc_prev_status = cc_status;
-         }
+         rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
+         if (note)
+           {
+             NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));
+             cc_prev_status = cc_status;
+           }
+       }
 #endif
 
        /* Detect insns that are really jump-tables
@@ -1945,8 +1957,10 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
            int vlen, idx;
 #endif
 
-           if (prescan > 0)
-             break;
+           if (! JUMP_TABLES_IN_TEXT_SECTION)
+             targetm.asm_out.function_rodata_section (current_function_decl);
+           else
+             current_function_section (current_function_decl);
 
            if (app_on)
              {
@@ -1960,7 +1974,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
 #ifdef ASM_OUTPUT_ADDR_VEC
                ASM_OUTPUT_ADDR_VEC (PREV_INSN (insn), body);
 #else
-               abort ();
+               gcc_unreachable ();
 #endif
              }
            else
@@ -1968,7 +1982,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
 #ifdef ASM_OUTPUT_ADDR_DIFF_VEC
                ASM_OUTPUT_ADDR_DIFF_VEC (PREV_INSN (insn), body);
 #else
-               abort ();
+               gcc_unreachable ();
 #endif
              }
 #else
@@ -1981,7 +1995,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
                    ASM_OUTPUT_ADDR_VEC_ELT
                      (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
 #else
-                   abort ();
+                   gcc_unreachable ();
 #endif
                  }
                else
@@ -1993,7 +2007,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
                       CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
                       CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));
 #else
-                   abort ();
+                   gcc_unreachable ();
 #endif
                  }
              }
@@ -2004,7 +2018,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
 #endif
 #endif
 
-           function_section (current_function_decl);
+           current_function_section (current_function_decl);
 
            break;
          }
@@ -2021,8 +2035,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
 
            /* There's no telling what that did to the condition codes.  */
            CC_STATUS_INIT;
-           if (prescan > 0)
-             break;
 
            if (string[0])
              {
@@ -2045,8 +2057,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
 
            /* There's no telling what that did to the condition codes.  */
            CC_STATUS_INIT;
-           if (prescan > 0)
-             break;
 
            /* Get out the operand values.  */
            string = decode_asm_operands (body, ops, NULL, NULL, NULL);
@@ -2054,6 +2064,10 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
            insn_noperands = noperands;
            this_is_asm_operands = insn;
 
+#ifdef FINAL_PRESCAN_INSN
+           FINAL_PRESCAN_INSN (insn, ops, insn_noperands);
+#endif
+
            /* Output the insn using them.  */
            if (string[0])
              {
@@ -2069,7 +2083,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
            break;
          }
 
-       if (prescan <= 0 && app_on)
+       if (app_on)
          {
            fputs (ASM_APP_OFF, file);
            app_on = 0;
@@ -2079,10 +2093,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
          {
            /* A delayed-branch sequence */
            int i;
-           rtx next;
 
-           if (prescan > 0)
-             break;
            final_sequence = body;
 
            /* Record the delay slots' frame information before the branch.
@@ -2090,7 +2101,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
 #if defined (DWARF2_UNWIND_INFO)
            if (dwarf2out_do_frame ())
              for (i = 1; i < XVECLEN (body, 0); i++)
-               dwarf2out_frame_debug (XVECEXP (body, 0, i));
+               dwarf2out_frame_debug (XVECEXP (body, 0, i), false);
 #endif
 
            /* The first insn in this SEQUENCE might be a JUMP_INSN that will
@@ -2098,7 +2109,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
               thought unnecessary.  If that happens, cancel this sequence
               and cause that insn to be restored.  */
 
-           next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, prescan, 1);
+           next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, 1, seen);
            if (next != XVECEXP (body, 0, 1))
              {
                final_sequence = 0;
@@ -2112,7 +2123,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
                /* We loop in case any instruction in a delay slot gets
                   split.  */
                do
-                 insn = final_scan_insn (insn, file, 0, prescan, 1);
+                 insn = final_scan_insn (insn, file, 0, 1, seen);
                while (insn != next);
              }
 #ifdef DBR_OUTPUT_SEQEND
@@ -2125,7 +2136,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
               called function.  Hence we don't preserve any CC-setting
               actions in these insns and the CC must be marked as being
               clobbered by the function.  */
-           if (GET_CODE (XVECEXP (body, 0, 0)) == CALL_INSN)
+           if (CALL_P (XVECEXP (body, 0, 0)))
              {
                CC_STATUS_INIT;
              }
@@ -2149,10 +2160,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
 
        if (optimize)
          {
-#if 0
-           rtx set = single_set (insn);
-#endif
-
            if (set
                && GET_CODE (SET_DEST (set)) == CC0
                && insn != last_ignored_compare)
@@ -2187,20 +2194,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
          }
 #endif
 
-#ifndef STACK_REGS
-       /* Don't bother outputting obvious no-ops, even without -O.
-          This optimization is fast and doesn't interfere with debugging.
-          Don't do this if the insn is in a delay slot, since this
-          will cause an improper number of delay insns to be written.  */
-       if (final_sequence == 0
-           && prescan >= 0
-           && GET_CODE (insn) == INSN && GET_CODE (body) == SET
-           && GET_CODE (SET_SRC (body)) == REG
-           && GET_CODE (SET_DEST (body)) == REG
-           && REGNO (SET_SRC (body)) == REGNO (SET_DEST (body)))
-         break;
-#endif
-
 #ifdef HAVE_cc0
        /* If this is a conditional branch, maybe modify it
           if the cc's are in a nonstandard state
@@ -2208,15 +2201,12 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
           do straightforwardly if the cc's were set up normally.  */
 
        if (cc_status.flags != 0
-           && GET_CODE (insn) == JUMP_INSN
+           && JUMP_P (insn)
            && GET_CODE (body) == SET
            && SET_DEST (body) == pc_rtx
            && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE
-           && GET_RTX_CLASS (GET_CODE (XEXP (SET_SRC (body), 0))) == '<'
-           && XEXP (XEXP (SET_SRC (body), 0), 0) == cc0_rtx
-           /* This is done during prescan; it is not done again
-              in final scan when prescan has been done.  */
-           && prescan >= 0)
+           && COMPARISON_P (XEXP (SET_SRC (body), 0))
+           && XEXP (XEXP (SET_SRC (body), 0), 0) == cc0_rtx)
          {
            /* This function may alter the contents of its argument
               and clear some of the cc_status.flags bits.
@@ -2257,7 +2247,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
          {
            rtx cond_rtx, then_rtx, else_rtx;
 
-           if (GET_CODE (insn) != JUMP_INSN
+           if (!JUMP_P (insn)
                && GET_CODE (SET_SRC (set)) == IF_THEN_ELSE)
              {
                cond_rtx = XEXP (SET_SRC (set), 0);
@@ -2316,14 +2306,16 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
               emit them before the peephole.  */
            if (next != 0 && next != NEXT_INSN (insn))
              {
-               rtx prev = PREV_INSN (insn);
+               rtx note, prev = PREV_INSN (insn);
 
                for (note = NEXT_INSN (insn); note != next;
                     note = NEXT_INSN (note))
-                 final_scan_insn (note, file, optimize, prescan, nopeepholes);
+                 final_scan_insn (note, file, optimize, nopeepholes, seen);
 
-               /* In case this is prescan, put the notes
-                  in proper position for later rescan.  */
+               /* Put the notes in the proper position for a later
+                  rescan.  For example, the SH target can do this
+                  when generating a far jump in a delayed branch
+                  sequence.  */
                note = NEXT_INSN (insn);
                PREV_INSN (note) = prev;
                NEXT_INSN (prev) = note;
@@ -2385,8 +2377,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
        current_output_insn = debug_insn = insn;
 
 #if defined (DWARF2_UNWIND_INFO)
-       if (GET_CODE (insn) == CALL_INSN && dwarf2out_do_frame ())
-         dwarf2out_frame_debug (insn);
+       if (CALL_P (insn) && dwarf2out_do_frame ())
+         dwarf2out_frame_debug (insn, false);
 #endif
 
        /* Find the proper template for this insn.  */
@@ -2399,8 +2391,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
          {
            rtx prev;
 
-           if (prev_nonnote_insn (insn) != last_ignored_compare)
-             abort ();
+           gcc_assert (prev_nonnote_insn (insn) == last_ignored_compare);
 
            /* We have already processed the notes between the setter and
               the user.  Make sure we don't process them again, this is
@@ -2410,7 +2401,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
                 prev != last_ignored_compare;
                 prev = PREV_INSN (prev))
              {
-               if (GET_CODE (prev) == NOTE)
+               if (NOTE_P (prev))
                  delete_insn (prev);   /* Use delete_note.  */
              }
 
@@ -2431,47 +2422,34 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
            /* This instruction should have been split in shorten_branches,
               to ensure that we would have valid length info for the
               splitees.  */
-           abort ();
+           gcc_unreachable ();
 #endif
 
            return new;
          }
 
-       if (prescan > 0)
-         break;
-
-#ifdef IA64_UNWIND_INFO
-       IA64_UNWIND_EMIT (asm_out_file, insn);
+#ifdef TARGET_UNWIND_INFO
+       /* ??? This will put the directives in the wrong place if
+          get_insn_template outputs assembly directly.  However calling it
+          before get_insn_template breaks if the insns is split.  */
+       targetm.asm_out.unwind_emit (asm_out_file, insn);
 #endif
-       /* Output assembler code from the template.  */
 
+       /* Output assembler code from the template.  */
        output_asm_insn (template, recog_data.operand);
 
        /* If necessary, report the effect that the instruction has on
           the unwind info.   We've already done this for delay slots
           and call instructions.  */
 #if defined (DWARF2_UNWIND_INFO)
-       if (GET_CODE (insn) == INSN
+       if (final_sequence == 0
 #if !defined (HAVE_prologue)
            && !ACCUMULATE_OUTGOING_ARGS
 #endif
-           && final_sequence == 0
            && dwarf2out_do_frame ())
-         dwarf2out_frame_debug (insn);
-#endif
-
-#if 0
-       /* It's not at all clear why we did this and doing so used to
-          interfere with tests that used REG_WAS_0 notes, which are
-          now gone, so let's try with this out.  */
-
-       /* Mark this insn as having been output.  */
-       INSN_DELETED_P (insn) = 1;
+         dwarf2out_frame_debug (insn, true);
 #endif
 
-       /* Emit information for vtable gc.  */
-       note = find_reg_note (insn, REG_VTABLE_REF, NULL_RTX);
-
        current_output_insn = debug_insn = 0;
       }
     }
@@ -2517,7 +2495,7 @@ cleanup_subreg_operands (rtx insn)
        recog_data.operand[i] = alter_subreg (recog_data.operand_loc[i]);
       else if (GET_CODE (recog_data.operand[i]) == PLUS
               || GET_CODE (recog_data.operand[i]) == MULT
-              || GET_CODE (recog_data.operand[i]) == MEM)
+              || MEM_P (recog_data.operand[i]))
        recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i]);
     }
 
@@ -2527,7 +2505,7 @@ cleanup_subreg_operands (rtx insn)
        *recog_data.dup_loc[i] = alter_subreg (recog_data.dup_loc[i]);
       else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS
               || GET_CODE (*recog_data.dup_loc[i]) == MULT
-              || GET_CODE (*recog_data.dup_loc[i]) == MEM)
+              || MEM_P (*recog_data.dup_loc[i]))
        *recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i]);
     }
 }
@@ -2543,8 +2521,25 @@ alter_subreg (rtx *xp)
 
   /* simplify_subreg does not remove subreg from volatile references.
      We are required to.  */
-  if (GET_CODE (y) == MEM)
-    *xp = adjust_address (y, GET_MODE (x), SUBREG_BYTE (x));
+  if (MEM_P (y))
+    {
+      int offset = SUBREG_BYTE (x);
+
+      /* For paradoxical subregs on big-endian machines, SUBREG_BYTE
+        contains 0 instead of the proper offset.  See simplify_subreg.  */
+      if (offset == 0
+         && GET_MODE_SIZE (GET_MODE (y)) < GET_MODE_SIZE (GET_MODE (x)))
+        {
+          int difference = GET_MODE_SIZE (GET_MODE (y))
+                          - GET_MODE_SIZE (GET_MODE (x));
+          if (WORDS_BIG_ENDIAN)
+            offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+          if (BYTES_BIG_ENDIAN)
+            offset += difference % UNITS_PER_WORD;
+        }
+
+      *xp = adjust_address (y, GET_MODE (x), offset);
+    }
   else
     {
       rtx new = simplify_subreg (GET_MODE (x), y, GET_MODE (y),
@@ -2552,14 +2547,12 @@ alter_subreg (rtx *xp)
 
       if (new != 0)
        *xp = new;
-      /* Simplify_subreg can't handle some REG cases, but we have to.  */
-      else if (GET_CODE (y) == REG)
+      else if (REG_P (y))
        {
-         unsigned int regno = subreg_hard_regno (x, 1);
+         /* Simplify_subreg can't handle some REG cases, but we have to.  */
+         unsigned int regno = subreg_regno (x);
          *xp = gen_rtx_REG_offset (y, GET_MODE (x), regno, SUBREG_BYTE (x));
        }
-      else
-       abort ();
     }
 
   return *xp;
@@ -2575,11 +2568,13 @@ walk_alter_subreg (rtx *xp)
     {
     case PLUS:
     case MULT:
+    case AND:
       XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
       XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1));
       break;
 
     case MEM:
+    case ZERO_EXTEND:
       XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
       break;
 
@@ -2708,7 +2703,7 @@ alter_cond (rtx cond)
     switch (GET_CODE (cond))
       {
       default:
-       abort ();
+       gcc_unreachable ();
 
       case NE:
        PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT);
@@ -2767,7 +2762,7 @@ output_operand_lossage (const char *msgid, ...)
 
   va_start (ap, msgid);
 
-  pfx_str = this_is_asm_operands ? _("invalid `asm': ") : "output_operand: ";
+  pfx_str = this_is_asm_operands ? _("invalid 'asm': ") : "output_operand: ";
   asprintf (&fmt_string, "%s%s", pfx_str, _(msgid));
   vasprintf (&new_message, fmt_string, ap);
 
@@ -2819,9 +2814,9 @@ get_mem_expr_from_op (rtx op, int *paddressp)
 
   *paddressp = 0;
 
-  if (GET_CODE (op) == REG)
+  if (REG_P (op))
     return REG_EXPR (op);
-  else if (GET_CODE (op) != MEM)
+  else if (!MEM_P (op))
     return 0;
 
   if (MEM_EXPR (op) != 0)
@@ -2840,8 +2835,8 @@ get_mem_expr_from_op (rtx op, int *paddressp)
           && (expr = get_mem_expr_from_op (XEXP (op, 1), &inner_addressp)))
     return expr;
 
-  while (GET_RTX_CLASS (GET_CODE (op)) == '1'
-        || GET_RTX_CLASS (GET_CODE (op)) == '2')
+  while (GET_RTX_CLASS (GET_CODE (op)) == RTX_UNARY
+        || GET_RTX_CLASS (GET_CODE (op)) == RTX_BIN_ARITH)
     op = XEXP (op, 0);
 
   expr = get_mem_expr_from_op (op, &inner_addressp);
@@ -3020,61 +3015,66 @@ output_asm_insn (const char *template, rtx *operands)
        else if (ISALPHA (*p))
          {
            int letter = *p++;
-           c = atoi (p);
-
-           if (! ISDIGIT (*p))
-             output_operand_lossage ("operand number missing after %%-letter");
-           else if (this_is_asm_operands
-                    && (c < 0 || (unsigned int) c >= insn_noperands))
+           unsigned long opnum;
+           char *endptr;
+           
+           opnum = strtoul (p, &endptr, 10);
+
+           if (endptr == p)
+             output_operand_lossage ("operand number missing "
+                                     "after %%-letter");
+           else if (this_is_asm_operands && opnum >= insn_noperands)
              output_operand_lossage ("operand number out of range");
            else if (letter == 'l')
-             output_asm_label (operands[c]);
+             output_asm_label (operands[opnum]);
            else if (letter == 'a')
-             output_address (operands[c]);
+             output_address (operands[opnum]);
            else if (letter == 'c')
              {
-               if (CONSTANT_ADDRESS_P (operands[c]))
-                 output_addr_const (asm_out_file, operands[c]);
+               if (CONSTANT_ADDRESS_P (operands[opnum]))
+                 output_addr_const (asm_out_file, operands[opnum]);
                else
-                 output_operand (operands[c], 'c');
+                 output_operand (operands[opnum], 'c');
              }
            else if (letter == 'n')
              {
-               if (GET_CODE (operands[c]) == CONST_INT)
+               if (GET_CODE (operands[opnum]) == CONST_INT)
                  fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC,
-                          - INTVAL (operands[c]));
+                          - INTVAL (operands[opnum]));
                else
                  {
                    putc ('-', asm_out_file);
-                   output_addr_const (asm_out_file, operands[c]);
+                   output_addr_const (asm_out_file, operands[opnum]);
                  }
              }
            else
-             output_operand (operands[c], letter);
+             output_operand (operands[opnum], letter);
 
-           if (!opoutput[c])
-             oporder[ops++] = c;
-           opoutput[c] = 1;
+           if (!opoutput[opnum])
+             oporder[ops++] = opnum;
+           opoutput[opnum] = 1;
 
-           while (ISDIGIT (c = *p))
-             p++;
+           p = endptr;
+           c = *p;
          }
        /* % followed by a digit outputs an operand the default way.  */
        else if (ISDIGIT (*p))
          {
-           c = atoi (p);
-           if (this_is_asm_operands
-               && (c < 0 || (unsigned int) c >= insn_noperands))
+           unsigned long opnum;
+           char *endptr;
+           
+           opnum = strtoul (p, &endptr, 10);
+           if (this_is_asm_operands && opnum >= insn_noperands)
              output_operand_lossage ("operand number out of range");
            else
-             output_operand (operands[c], 0);
+             output_operand (operands[opnum], 0);
 
-           if (!opoutput[c])
-             oporder[ops++] = c;
-           opoutput[c] = 1;
+           if (!opoutput[opnum])
+             oporder[ops++] = opnum;
+           opoutput[opnum] = 1;
 
-           while (ISDIGIT (c = *p))
-             p++;
+           p = endptr;
+           c = *p;
          }
        /* % followed by punctuation: output something for that
           punctuation character alone, with no operand.
@@ -3109,12 +3109,12 @@ output_asm_label (rtx x)
 
   if (GET_CODE (x) == LABEL_REF)
     x = XEXP (x, 0);
-  if (GET_CODE (x) == CODE_LABEL
-      || (GET_CODE (x) == NOTE
+  if (LABEL_P (x)
+      || (NOTE_P (x)
          && NOTE_LINE_NUMBER (x) == NOTE_INSN_DELETED_LABEL))
     ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
   else
-    output_operand_lossage ("`%%l' operand isn't a label");
+    output_operand_lossage ("'%%l' operand isn't a label");
 
   assemble_name (asm_out_file, buf);
 }
@@ -3137,9 +3137,7 @@ output_operand (rtx x, int code ATTRIBUTE_UNUSED)
 
   /* If X is a pseudo-register, abort now rather than writing trash to the
      assembler file.  */
-
-  if (x && GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
-    abort ();
+  gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER);
 
   PRINT_OPERAND (asm_out_file, x, code);
 }
@@ -3422,7 +3420,7 @@ asm_fprintf (FILE *file, const char *p, ...)
            break;
 
 #ifdef ASM_FPRINTF_EXTENSIONS
-           /* Upper case letters are reserved for general use by asm_fprintf
+           /* Uppercase letters are reserved for general use by asm_fprintf
               and so are not available to target specific code.  In order to
               prevent the ASM_FPRINTF_EXTENSIONS macro from using them then,
               they are defined here.  As they get turned into real extensions
@@ -3436,7 +3434,7 @@ asm_fprintf (FILE *file, const char *p, ...)
          ASM_FPRINTF_EXTENSIONS (file, argptr, p)
 #endif
          default:
-           abort ();
+           gcc_unreachable ();
          }
        break;
 
@@ -3583,8 +3581,8 @@ split_double (rtx value, rtx *first, rtx *second)
        }
 #endif
 
-      *first = GEN_INT ((HOST_WIDE_INT) l[0]);
-      *second = GEN_INT ((HOST_WIDE_INT) l[1]);
+      *first = GEN_INT (l[0]);
+      *second = GEN_INT (l[1]);
     }
 }
 \f
@@ -3601,12 +3599,12 @@ leaf_function_p (void)
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     {
-      if (GET_CODE (insn) == CALL_INSN
+      if (CALL_P (insn)
          && ! SIBLING_CALL_P (insn))
        return 0;
-      if (GET_CODE (insn) == INSN
+      if (NONJUMP_INSN_P (insn)
          && GET_CODE (PATTERN (insn)) == SEQUENCE
-         && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN
+         && CALL_P (XVECEXP (PATTERN (insn), 0, 0))
          && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
        return 0;
     }
@@ -3616,12 +3614,12 @@ leaf_function_p (void)
     {
       insn = XEXP (link, 0);
 
-      if (GET_CODE (insn) == CALL_INSN
+      if (CALL_P (insn)
          && ! SIBLING_CALL_P (insn))
        return 0;
-      if (GET_CODE (insn) == INSN
+      if (NONJUMP_INSN_P (insn)
          && GET_CODE (PATTERN (insn)) == SEQUENCE
-         && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN
+         && CALL_P (XVECEXP (PATTERN (insn), 0, 0))
          && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
        return 0;
     }
@@ -3637,13 +3635,12 @@ int
 final_forward_branch_p (rtx insn)
 {
   int insn_id, label_id;
-  if (!uid_shuid)
-    abort ();
+  
+  gcc_assert (uid_shuid);
   insn_id = INSN_SHUID (insn);
   label_id = INSN_SHUID (JUMP_LABEL (insn));
   /* We've hit some insns that does not have id information available.  */
-  if (!insn_id || !label_id)
-    abort ();
+  gcc_assert (insn_id && label_id);
   return insn_id < label_id;
 }
 
@@ -3674,7 +3671,7 @@ only_leaf_regs_used (void)
 
   if (current_function_uses_pic_offset_table
       && pic_offset_table_rtx != 0
-      && GET_CODE (pic_offset_table_rtx) == REG
+      && REG_P (pic_offset_table_rtx)
       && ! permitted_reg_in_leaf_functions[REGNO (pic_offset_table_rtx)])
     return 0;
 
@@ -3718,7 +3715,7 @@ leaf_renumber_regs_insn (rtx in_rtx)
      renumbered_regs would be 1 for an output-register;
      they  */
 
-  if (GET_CODE (in_rtx) == REG)
+  if (REG_P (in_rtx))
     {
       int newreg;
 
@@ -3735,8 +3732,7 @@ leaf_renumber_regs_insn (rtx in_rtx)
          return;
        }
       newreg = LEAF_REG_REMAP (newreg);
-      if (newreg < 0)
-       abort ();
+      gcc_assert (newreg >= 0);
       regs_ever_live[REGNO (in_rtx)] = 0;
       regs_ever_live[newreg] = 1;
       REGNO (in_rtx) = newreg;
@@ -3779,7 +3775,7 @@ leaf_renumber_regs_insn (rtx in_rtx)
        break;
 
       default:
-       abort ();
+       gcc_unreachable ();
       }
 }
 #endif
@@ -3790,7 +3786,7 @@ leaf_renumber_regs_insn (rtx in_rtx)
    calls into this file, i.e., dbxout_symbol, dbxout_parms, and dbxout_reg_params.
    Those routines may also be called from a higher level intercepted routine. So
    to prevent recording data for an inner call to one of these for an intercept,
-   we maintain a intercept nesting counter (debug_nesting). We only save the
+   we maintain an intercept nesting counter (debug_nesting). We only save the
    intercepted arguments if the nesting is 1.  */
 int debug_nesting = 0;