OSDN Git Service

* final.c (final): Fix typo reported by Aaron W. LaFramboise.
[pf3gnuchains/gcc-fork.git] / gcc / final.c
index 9725c0b..a264fca 100644 (file)
@@ -1,6 +1,6 @@
 /* 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 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -46,6 +46,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 
 #include "tree.h"
 #include "rtl.h"
@@ -68,6 +70,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "target.h"
 #include "debug.h"
 #include "expr.h"
+#include "cfglayout.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"          /* Needed for external data
@@ -78,6 +81,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "dwarf2out.h"
 #endif
 
+#ifdef DBX_DEBUGGING_INFO
+#include "dbxout.h"
+#endif
+
 /* If we aren't using cc0, CC_STATUS_INIT shouldn't exist.  So define a
    null default for it to save conditionalization later.  */
 #ifndef CC_STATUS_INIT
@@ -98,6 +105,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define JUMP_TABLES_IN_TEXT_SECTION 0
 #endif
 
+#if defined(READONLY_DATA_SECTION) || defined(READONLY_DATA_SECTION_ASM_OP)
+#define HAVE_READONLY_DATA_SECTION 1
+#else
+#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;
@@ -114,15 +132,12 @@ static int high_function_linenum;
 /* Filename of last NOTE.  */
 static const char *last_filename;
 
-/* Number of instrumented arcs when profile_arc_flag is set.  */
-extern int count_instrumented_edges;
-
 extern int length_unit_log; /* This is defined in insn-attrtab.c.  */
 
 /* Nonzero while outputting an `asm' with operands.
    This means that inconsistencies are the user's fault, so don't abort.
    The precise value is the insn being output, to pass to error_for_asm.  */
-static rtx this_is_asm_operands;
+rtx this_is_asm_operands;
 
 /* Number of operands of this insn, for an `asm' with operands.  */
 static unsigned int insn_noperands;
@@ -131,10 +146,6 @@ static unsigned int insn_noperands;
 
 static rtx last_ignored_compare = 0;
 
-/* Flag indicating this insn is the start of a new basic block.  */
-
-static int new_block = 1;
-
 /* Assign a unique number to each insn that is output.
    This can be used to generate unique local labels.  */
 
@@ -164,15 +175,17 @@ CC_STATUS cc_prev_status;
 
 char regs_ever_live[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.  */
+/* 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.  */
 
-int frame_pointer_needed;
+char regs_asm_clobbered[FIRST_PSEUDO_REGISTER];
 
-/* Assign unique numbers to labels generated for profiling.  */
+/* Nonzero means current function must be given a frame pointer.
+   Initialized in function.c to 0.  Set only in reload1.c as per
+   the needs of the function.  */
 
-int profile_label_no;
+int frame_pointer_needed;
 
 /* Number of unmatched NOTE_INSN_BLOCK_BEG notes we have seen.  */
 
@@ -193,73 +206,40 @@ 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;
 #endif
 
-/* Linked list to hold line numbers for each basic block.  */
-
-struct bb_list
-{
-  struct bb_list *next;                /* pointer to next basic block */
-  int line_num;                        /* line number */
-  int file_label_num;          /* LPBC<n> label # for stored filename */
-  int func_label_num;          /* LPBC<n> label # for stored function name */
-};
-
-static struct bb_list *bb_head = 0;            /* Head of basic block list */
-static struct bb_list **bb_tail = &bb_head;    /* Ptr to store next bb ptr */
-static int bb_file_label_num   = -1;           /* Current label # for file */
-static int bb_func_label_num   = -1;           /* Current label # for func */
-
-/* Linked list to hold the strings for each file and function name output.  */
-
-struct bb_str
-{
-  struct bb_str *next;         /* pointer to next string */
-  const char *string;          /* string */
-  int label_num;               /* label number */
-  int length;                  /* string length */
-};
-
-static struct bb_str *sbb_head = 0;            /* Head of string list.  */
-static struct bb_str **sbb_tail        = &sbb_head;    /* Ptr to store next bb str */
-static int sbb_label_num       = 0;            /* Last label used */
-
 #ifdef HAVE_ATTR_length
-static int asm_insn_count      PARAMS ((rtx));
-#endif
-static void profile_function   PARAMS ((FILE *));
-static void profile_after_prologue PARAMS ((FILE *));
-static void notice_source_line PARAMS ((rtx));
-static rtx walk_alter_subreg   PARAMS ((rtx *));
-static void output_asm_name    PARAMS ((void));
-static tree get_mem_expr_from_op       PARAMS ((rtx, int *));
-static void output_asm_operand_names PARAMS ((rtx *, int *, int));
-static void output_operand     PARAMS ((rtx, int));
+static int asm_insn_count (rtx);
+#endif
+static void profile_function (FILE *);
+static void profile_after_prologue (FILE *);
+static bool notice_source_line (rtx);
+static rtx walk_alter_subreg (rtx *);
+static void output_asm_name (void);
+static void output_alternate_entry_point (FILE *, rtx);
+static tree get_mem_expr_from_op (rtx, int *);
+static void output_asm_operand_names (rtx *, int *, int);
+static void output_operand (rtx, int);
 #ifdef LEAF_REGISTERS
-static void leaf_renumber_regs PARAMS ((rtx));
+static void leaf_renumber_regs (rtx);
 #endif
 #ifdef HAVE_cc0
-static int alter_cond          PARAMS ((rtx));
+static int alter_cond (rtx);
 #endif
 #ifndef ADDR_VEC_ALIGN
-static int final_addr_vec_align PARAMS ((rtx));
+static int final_addr_vec_align (rtx);
 #endif
 #ifdef HAVE_ATTR_length
-static int align_fuzz          PARAMS ((rtx, rtx, int, unsigned));
+static int align_fuzz (rtx, rtx, int, unsigned);
 #endif
 \f
 /* Initialize data in final at the beginning of a compilation.  */
 
 void
-init_final (filename)
-     const char *filename ATTRIBUTE_UNUSED;
+init_final (const char *filename ATTRIBUTE_UNUSED)
 {
   app_on = 0;
   final_sequence = 0;
@@ -269,160 +249,19 @@ init_final (filename)
 #endif
 }
 
-/* Called at end of source file,
-   to output the block-profiling table for this entire compilation.  */
-
-void
-end_final (filename)
-     const char *filename;
-{
-  int i;
-
-  if (profile_arc_flag)
-    {
-      char name[20];
-      int align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
-      int size, rounded;
-      struct bb_list *ptr;
-      struct bb_str *sptr;
-      int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT;
-      int gcov_type_bytes = GCOV_TYPE_SIZE / BITS_PER_UNIT;
-      int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT;
-      unsigned int align2 = LONG_TYPE_SIZE;
-
-      size = gcov_type_bytes * count_instrumented_edges;
-      rounded = size;
-
-      rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
-      rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
-                * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
-
-      /* ??? This _really_ ought to be done with a structure layout
-        and with assemble_constructor.  If long_bytes != pointer_bytes
-        we'll be emitting unaligned data at some point.  */
-      if (long_bytes != pointer_bytes)
-       abort ();
-
-      data_section ();
-
-      /* Output the main header, of 11 words:
-        0:  1 if this file is initialized, else 0.
-        1:  address of file name (LPBX1).
-        2:  address of table of counts (LPBX2).
-        3:  number of counts in the table.
-        4:  always 0, for compatibility with Sun.
-
-         The following are GNU extensions:
-
-        5:  address of table of start addrs of basic blocks (LPBX3).
-        6:  Number of bytes in this header.
-        7:  address of table of function names (LPBX4).
-        8:  address of table of line numbers (LPBX5) or 0.
-        9:  address of table of file names (LPBX6) or 0.
-       10:  space reserved for basic block profiling.  */
-
-      ASM_OUTPUT_ALIGN (asm_out_file, align);
-
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0);
-
-      /* Zero word.  */
-      assemble_integer (const0_rtx, long_bytes, align2, 1);
-
-      /* Address of filename.  */
-      ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1);
-      assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
-                       align2, 1);
-
-      /* Address of count table.  */
-      ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
-      assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
-                       align2, 1);
-
-      /* Count of the # of instrumented arcs.  */
-      assemble_integer (GEN_INT (count_instrumented_edges),
-                       long_bytes, align2, 1);
-
-      /* Zero word (link field).  */
-      assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-
-      assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-
-      /* Byte count for extended structure.  */
-      assemble_integer (GEN_INT (11 * UNITS_PER_WORD), long_bytes, align2, 1);
-
-      /* Address of function name table.  */
-      assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-
-      /* Address of line number and filename tables if debugging.  */
-      assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-      assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-
-      /* Space for extension ptr (link field).  */
-      assemble_integer (const0_rtx, UNITS_PER_WORD, align2, 1);
-
-      /* Output the file name changing the suffix to .d for
-        Sun tcov compatibility.  */
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1);
-      {
-       char *cwd = getpwd ();
-       int len = strlen (filename) + strlen (cwd) + 1;
-       char *data_file = (char *) alloca (len + 4);
-
-       strcpy (data_file, cwd);
-       strcat (data_file, "/");
-       strcat (data_file, filename);
-       strip_off_ending (data_file, len);
-       strcat (data_file, ".da");
-       assemble_string (data_file, strlen (data_file) + 1);
-      }
-
-      /* Make space for the table of counts.  */
-      if (size == 0)
-       {
-         /* Realign data section.  */
-         ASM_OUTPUT_ALIGN (asm_out_file, align);
-         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2);
-         if (size != 0)
-           assemble_zeros (size);
-       }
-      else
-       {
-         ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
-#ifdef ASM_OUTPUT_SHARED_LOCAL
-         if (flag_shared_data)
-           ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded);
-         else
-#endif
-#ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL
-           ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name,
-                                          size, BIGGEST_ALIGNMENT);
-#else
-#ifdef ASM_OUTPUT_ALIGNED_LOCAL
-           ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size,
-                                     BIGGEST_ALIGNMENT);
-#else
-           ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
-#endif
-#endif
-       }
-    }
-}
-
 /* Default target function prologue and epilogue assembler output.
 
    If not overridden for epilogue code, then the function body itself
    contains return instructions wherever needed.  */
 void
-default_function_pro_epilogue (file, size)
-     FILE *file ATTRIBUTE_UNUSED;
-     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+default_function_pro_epilogue (FILE *file ATTRIBUTE_UNUSED,
+                              HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 {
 }
 
 /* Default target hook that outputs nothing to a stream.  */
 void
-no_asm_to_stream (file)
-     FILE *file ATTRIBUTE_UNUSED;
+no_asm_to_stream (FILE *file ATTRIBUTE_UNUSED)
 {
 }
 
@@ -430,7 +269,7 @@ no_asm_to_stream (file)
    Used before the output from an `asm' statement.  */
 
 void
-app_enable ()
+app_enable (void)
 {
   if (! app_on)
     {
@@ -443,7 +282,7 @@ app_enable ()
    Called from varasm.c before most kinds of output.  */
 
 void
-app_disable ()
+app_disable (void)
 {
   if (app_on)
     {
@@ -458,7 +297,7 @@ app_disable ()
 
 #ifdef DELAY_SLOTS
 int
-dbr_sequence_length ()
+dbr_sequence_length (void)
 {
   if (final_sequence != 0)
     return XVECLEN (final_sequence, 0) - 1;
@@ -475,9 +314,7 @@ dbr_sequence_length ()
 
 static int *insn_lengths;
 
-#ifdef HAVE_ATTR_length
 varray_type insn_addresses_;
-#endif
 
 /* Max uid for which the above arrays are valid.  */
 static int insn_lengths_max_uid;
@@ -488,7 +325,7 @@ int insn_current_address;
 /* Address of insn being processed in previous iteration.  */
 int insn_last_address;
 
-/* konwn invariant alignment of insn being processed.  */
+/* known invariant alignment of insn being processed.  */
 int insn_current_align;
 
 /* After shorten_branches, for any insn, uid_align[INSN_UID (insn)]
@@ -513,7 +350,7 @@ static struct label_alignment *label_align;
 /* Indicate that branch shortening hasn't yet been done.  */
 
 void
-init_insn_lengths ()
+init_insn_lengths (void)
 {
   if (uid_shuid)
     {
@@ -540,8 +377,7 @@ init_insn_lengths ()
    get its actual length.  Otherwise, get its maximum length.  */
 
 int
-get_attr_length (insn)
-     rtx insn ATTRIBUTE_UNUSED;
+get_attr_length (rtx insn ATTRIBUTE_UNUSED)
 {
 #ifdef HAVE_ATTR_length
   rtx body;
@@ -564,7 +400,7 @@ get_attr_length (insn)
 
       case JUMP_INSN:
        body = PATTERN (insn);
-        if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
+       if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
          {
            /* Alignment is machine-dependent and should be handled by
               ADDR_VEC_ALIGN.  */
@@ -675,8 +511,7 @@ get_attr_length (insn)
 
 #ifndef ADDR_VEC_ALIGN
 static int
-final_addr_vec_align (addr_vec)
-     rtx addr_vec;
+final_addr_vec_align (rtx addr_vec)
 {
   int align = GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec)));
 
@@ -706,8 +541,7 @@ static int min_labelno, max_labelno;
 /* For the benefit of port specific code do this also as a function.  */
 
 int
-label_to_alignment (label)
-     rtx label;
+label_to_alignment (rtx label)
 {
   return LABEL_TO_ALIGNMENT (label);
 }
@@ -730,7 +564,7 @@ label_to_alignment (label)
    For casesi tables, we also want to know worst case minimum amounts of
    address difference, in case a machine description wants to introduce
    some common offset that is added to all offsets in a table.
-   For this purpose, align_fuzz with a growth argument of 0 comuptes the
+   For this purpose, align_fuzz with a growth argument of 0 computes the
    appropriate adjustment.  */
 
 /* Compute the maximum delta by which the difference of the addresses of
@@ -742,10 +576,7 @@ label_to_alignment (label)
    The return value is undefined for any other value of GROWTH.  */
 
 static int
-align_fuzz (start, end, known_align_log, growth)
-     rtx start, end;
-     int known_align_log;
-     unsigned growth;
+align_fuzz (rtx start, rtx end, int known_align_log, unsigned int growth)
 {
   int uid = INSN_UID (start);
   rtx align_label;
@@ -784,8 +615,7 @@ align_fuzz (start, end, known_align_log, growth)
    to exclude the branch size.  */
 
 int
-insn_current_reference_address (branch)
-     rtx branch;
+insn_current_reference_address (rtx branch)
 {
   rtx dest, seq;
   int seq_uid;
@@ -822,10 +652,10 @@ insn_current_reference_address (branch)
 #endif /* HAVE_ATTR_length */
 \f
 void
-compute_alignments ()
+compute_alignments (void)
 {
-  int i;
   int log, max_skip, max_log;
+  basic_block bb;
 
   if (label_align)
     {
@@ -835,21 +665,21 @@ compute_alignments ()
 
   max_labelno = max_label_num ();
   min_labelno = get_first_label_num ();
-  label_align = (struct label_alignment *)
-    xcalloc (max_labelno - min_labelno + 1, sizeof (struct label_alignment));
+  label_align = xcalloc (max_labelno - min_labelno + 1,
+                        sizeof (struct label_alignment));
 
   /* If not optimizing or optimizing for size, don't assign any alignments.  */
   if (! optimize || optimize_size)
     return;
 
-  for (i = 0; i < n_basic_blocks; i++)
+  FOR_EACH_BB (bb)
     {
-      basic_block bb = BASIC_BLOCK (i);
-      rtx label = bb->head;
+      rtx label = BB_HEAD (bb);
       int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0;
       edge e;
 
-      if (GET_CODE (label) != CODE_LABEL)
+      if (GET_CODE (label) != CODE_LABEL
+         || probably_never_executed_bb_p (bb))
        continue;
       max_log = LABEL_ALIGN (label);
       max_skip = LABEL_ALIGN_MAX_SKIP;
@@ -864,7 +694,7 @@ compute_alignments ()
 
       /* There are two purposes to align block with no fallthru incoming edge:
         1) to avoid fetch stalls when branch destination is near cache boundary
-        2) to improve cache effciency in case the previous block is not executed
+        2) to improve cache efficiency in case the previous block is not executed
            (so it does not need to be in the cache).
 
         We to catch first case, we align frequently executed blocks.
@@ -874,8 +704,8 @@ compute_alignments ()
 
       if (!has_fallthru
          && (branch_frequency > BB_FREQ_MAX / 10
-             || (bb->frequency > BASIC_BLOCK (i - 1)->frequency * 10
-                 && (BASIC_BLOCK (i - 1)->frequency
+             || (bb->frequency > bb->prev_bb->frequency * 10
+                 && (bb->prev_bb->frequency
                      <= ENTRY_BLOCK_PTR->frequency / 2))))
        {
          log = JUMP_ALIGN (label);
@@ -886,10 +716,11 @@ compute_alignments ()
            }
        }
       /* In case block is frequent and reached mostly by non-fallthru edge,
-        align it.  It is most likely an first block of loop.  */
+        align it.  It is most likely a first block of loop.  */
       if (has_fallthru
+         && maybe_hot_bb_p (bb)
          && branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10
-         && branch_frequency > fallthru_frequency * 5)
+         && branch_frequency > fallthru_frequency * 2)
        {
          log = LOOP_ALIGN (label);
          if (max_log < log)
@@ -906,23 +737,16 @@ compute_alignments ()
 /* 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
    by calling shorten_branches.  This cannot be collapsed with
-   shorten_branches itself into a single pass unless we also want to intergate
+   shorten_branches itself into a single pass unless we also want to integrate
    reorg.c, since the branch splitting exposes new instructions with delay
    slots.  */
 
 void
-shorten_branches (first)
-     rtx first ATTRIBUTE_UNUSED;
+shorten_branches (rtx first ATTRIBUTE_UNUSED)
 {
   rtx insn;
   int max_uid;
@@ -943,7 +767,10 @@ shorten_branches (first)
   /* Compute maximum UID and allocate label_align / uid_shuid.  */
   max_uid = get_max_uid ();
 
-  uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid);
+  /* Free uid_shuid before reallocating it.   */
+  free (uid_shuid);
+  
+  uid_shuid = xmalloc (max_uid * sizeof *uid_shuid);
 
   if (max_labelno != max_label_num ())
     {
@@ -956,8 +783,8 @@ shorten_branches (first)
       n_labels = max_labelno - min_labelno + 1;
       n_old_labels = old - min_labelno + 1;
 
-      label_align = (struct label_alignment *) xrealloc
-       (label_align, n_labels * sizeof (struct label_alignment));
+      label_align = xrealloc (label_align,
+                             n_labels * sizeof (struct label_alignment));
 
       /* Range of labels grows monotonically in the function.  Abort here
          means that the initialization of array got lost.  */
@@ -993,7 +820,7 @@ shorten_branches (first)
       else if (GET_CODE (insn) == CODE_LABEL)
        {
          rtx next;
-         
+
          /* Merge in alignments computed by compute_alignments.  */
          log = LABEL_TO_ALIGNMENT (insn);
          if (max_log < log)
@@ -1011,11 +838,7 @@ shorten_branches (first)
          next = NEXT_INSN (insn);
          /* ADDR_VECs only take room if read-only data goes into the text
             section.  */
-         if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
-             || 1
-#endif
-             )
+         if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
            if (next && GET_CODE (next) == JUMP_INSN)
              {
                rtx nextbody = PATTERN (next);
@@ -1056,20 +879,20 @@ shorten_branches (first)
 #ifdef HAVE_ATTR_length
 
   /* Allocate the rest of the arrays.  */
-  insn_lengths = (int *) xmalloc (max_uid * sizeof (*insn_lengths));
+  insn_lengths = xmalloc (max_uid * sizeof (*insn_lengths));
   insn_lengths_max_uid = max_uid;
   /* Syntax errors can lead to labels being outside of the main insn stream.
      Initialize insn_addresses, so that we get reproducible results.  */
   INSN_ADDRESSES_ALLOC (max_uid);
 
-  varying_length = (char *) xcalloc (max_uid, sizeof (char));
+  varying_length = xcalloc (max_uid, sizeof (char));
 
   /* Initialize uid_align.  We scan instructions
      from end to start, and keep in align_tab[n] the last seen insn
      that does an alignment of at least n+1, i.e. the successor
      in the alignment chain for an insn that does / has a known
      alignment of n.  */
-  uid_align = (rtx *) xcalloc (max_uid, sizeof *uid_align);
+  uid_align = xcalloc (max_uid, sizeof *uid_align);
 
   for (i = MAX_CODE_ALIGN; --i >= 0;)
     align_tab[i] = NULL_RTX;
@@ -1146,7 +969,7 @@ shorten_branches (first)
 #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))
     {
@@ -1165,7 +988,7 @@ shorten_branches (first)
            }
        }
 
-      INSN_ADDRESSES (uid) = insn_current_address;
+      INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
 
       if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER
          || GET_CODE (insn) == CODE_LABEL)
@@ -1178,11 +1001,7 @@ shorten_branches (first)
        {
          /* This only takes room if read-only data goes into the text
             section.  */
-         if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
-             || 1
-#endif
-             )
+         if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
            insn_lengths[uid] = (XVECLEN (body,
                                          GET_CODE (body) == ADDR_DIFF_VEC)
                                 * GET_MODE_SIZE (GET_MODE (body)));
@@ -1251,7 +1070,7 @@ shorten_branches (first)
     {
       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))
        {
@@ -1383,11 +1202,7 @@ shorten_branches (first)
              PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
                                                        max_addr - rel_addr,
                                                        body));
-             if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
-                 || 1
-#endif
-                 )
+             if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
                {
                  insn_lengths[uid]
                    = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
@@ -1417,7 +1232,7 @@ shorten_branches (first)
 
                      insn_current_address += insn_lengths[inner_uid];
                    }
-                }
+               }
              else
                insn_current_address += insn_lengths[uid];
 
@@ -1489,8 +1304,7 @@ shorten_branches (first)
    This is used to compute its length.  */
 
 static int
-asm_insn_count (body)
-     rtx body;
+asm_insn_count (rtx body)
 {
   const char *template;
   int count = 1;
@@ -1519,30 +1333,16 @@ asm_insn_count (body)
      test and compare insns.  */
 
 void
-final_start_function (first, file, optimize)
-     rtx first;
-     FILE *file;
-     int optimize ATTRIBUTE_UNUSED;
+final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
+                     int optimize ATTRIBUTE_UNUSED)
 {
   block_depth = 0;
 
   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;
+  last_filename = locator_file (prologue_locator);
+  last_linenum = locator_line (prologue_locator);
 
-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-       if (!call_used_regs[i])
-         regs_ever_live[i] = 1;
-    }
-#endif
-
-  if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED)
-    notice_source_line (first);
   high_block_linenum = high_function_linenum = last_linenum;
 
   (*debug_hooks->begin_prologue) (last_linenum, last_filename);
@@ -1560,7 +1360,7 @@ final_start_function (first, file, optimize)
   /* The Sun386i and perhaps other machines don't work right
      if the profiling code comes after the prologue.  */
 #ifdef PROFILE_BEFORE_PROLOGUE
-  if (profile_flag)
+  if (current_function_profile)
     profile_function (file);
 #endif /* PROFILE_BEFORE_PROLOGUE */
 
@@ -1574,7 +1374,7 @@ final_start_function (first, file, optimize)
   if (write_symbols)
     {
       remove_unnecessary_notes ();
-      reorder_blocks ();
+      reemit_insn_block_notes ();
       number_blocks (current_function_decl);
       /* We never actually put out begin/end notes for the top-level
         block in the function.  But, conceptually, that block is
@@ -1583,13 +1383,7 @@ final_start_function (first, file, optimize)
     }
 
   /* First output the function prologue: code to set up the stack frame.  */
-  (*targetm.asm_out.function_prologue) (file, get_frame_size ());
-
-#ifdef VMS_DEBUGGING_INFO
-  /* Output label after the prologue of the function.  */
-  if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
-    vmsdbgout_after_prologue ();
-#endif
+  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.  */
@@ -1597,55 +1391,45 @@ final_start_function (first, file, optimize)
   if (! HAVE_prologue)
 #endif
     profile_after_prologue (file);
-
-  profile_label_no++;
 }
 
 static void
-profile_after_prologue (file)
-     FILE *file ATTRIBUTE_UNUSED;
+profile_after_prologue (FILE *file ATTRIBUTE_UNUSED)
 {
 #ifndef PROFILE_BEFORE_PROLOGUE
-  if (profile_flag)
+  if (current_function_profile)
     profile_function (file);
 #endif /* not PROFILE_BEFORE_PROLOGUE */
 }
 
 static void
-profile_function (file)
-     FILE *file;
+profile_function (FILE *file ATTRIBUTE_UNUSED)
 {
 #ifndef NO_PROFILE_COUNTERS
-  int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
+# define NO_PROFILE_COUNTERS   0
 #endif
 #if defined(ASM_OUTPUT_REG_PUSH)
-#if defined(STRUCT_VALUE_INCOMING_REGNUM) || defined(STRUCT_VALUE_REGNUM)
   int sval = current_function_returns_struct;
-#endif
+  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 */
 
-#ifndef NO_PROFILE_COUNTERS
-  data_section ();
-  ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
-  ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no);
-  assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
-#endif
+  if (! NO_PROFILE_COUNTERS)
+    {
+      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);
+      assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
+    }
 
   function_section (current_function_decl);
 
-#if defined(STRUCT_VALUE_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
-  if (sval)
-    ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM);
-#else
-#if defined(STRUCT_VALUE_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
-  if (sval)
-    {
-      ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM);
-    }
-#endif
+#if defined(ASM_OUTPUT_REG_PUSH)
+  if (sval && svrtx != NULL_RTX && REG_P (svrtx))
+    ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx));
 #endif
 
 #if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
@@ -1660,7 +1444,7 @@ profile_function (file)
 #endif
 #endif
 
-  FUNCTION_PROFILER (file, profile_label_no);
+  FUNCTION_PROFILER (file, current_function_funcdef_no);
 
 #if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
   if (cxt)
@@ -1674,16 +1458,9 @@ profile_function (file)
 #endif
 #endif
 
-#if defined(STRUCT_VALUE_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
-  if (sval)
-    ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM);
-#else
-#if defined(STRUCT_VALUE_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
-  if (sval)
-    {
-      ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM);
-    }
-#endif
+#if defined(ASM_OUTPUT_REG_PUSH)
+  if (sval && svrtx != NULL_RTX && REG_P (svrtx))
+    ASM_OUTPUT_REG_POP (file, REGNO (svrtx));
 #endif
 }
 
@@ -1692,7 +1469,7 @@ profile_function (file)
    even though not all of them are needed.  */
 
 void
-final_end_function ()
+final_end_function (void)
 {
   app_disable ();
 
@@ -1700,18 +1477,16 @@ final_end_function ()
 
   /* 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) ();
+  (*debug_hooks->end_epilogue) (last_linenum, last_filename);
 
 #if defined (DWARF2_UNWIND_INFO)
   if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG
       && dwarf2out_do_frame ())
-    dwarf2out_end_epilogue ();
+    dwarf2out_end_epilogue (last_linenum, last_filename);
 #endif
-
-  bb_func_label_num = -1;      /* not in function, nuke label # */
 }
 \f
 /* Output assembler code for some insns: all or part of a function.
@@ -1726,60 +1501,45 @@ final_end_function ()
    Prescanning is done only on certain machines.  */
 
 void
-final (first, file, optimize, prescan)
-     rtx first;
-     FILE *file;
-     int optimize;
-     int prescan;
+final (rtx first, FILE *file, int optimize, int prescan)
 {
   rtx insn;
-  int max_line = 0;
   int max_uid = 0;
+  int seen = 0;
 
   last_ignored_compare = 0;
-  new_block = 1;
 
-  /* 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 ((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 = (char *) xcalloc (max_line + 1, sizeof (char));
 
   for (insn = first; insn; insn = NEXT_INSN (insn))
     {
-      if (INSN_UID (insn) > max_uid)       /* find largest UID */
+      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.  */
@@ -1804,65 +1564,118 @@ final (first, file, optimize, prescan)
 #ifdef HAVE_ATTR_length
       if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
        {
-#ifdef STACK_REGS
-         /* Irritatingly, the reg-stack pass is creating new instructions
-            and because of REG_DEAD note abuse it has to run after
-            shorten_branches.  Fake address of -1 then.  */
-         insn_current_address = -1;
-#else
          /* This can be triggered by bugs elsewhere in the compiler if
             new insns are created after init_insn_lengths is called.  */
-         abort ();
-#endif
+         if (GET_CODE (insn) == NOTE)
+           insn_current_address = -1;
+         else
+           abort ();
        }
       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, prescan, 0, &seen);
     }
-
-  free (line_note_exists);
-  line_note_exists = NULL;
 }
 \f
 const char *
-get_insn_template (code, insn)
-     int code;
-     rtx insn;
+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);
+      return (*insn_data[code].output.function) (recog_data.operand, insn);
+
+    default:
+      abort ();
+    }
+}
+
+/* Emit the appropriate declaration for an alternate-entry-point
+   symbol represented by INSN, to FILE.  INSN is a CODE_LABEL with
+   LABEL_KIND != LABEL_NORMAL.
+
+   The case fall-through in this function is intentional.  */
+static void
+output_alternate_entry_point (FILE *file, rtx insn)
+{
+  const char *name = LABEL_NAME (insn);
 
+  switch (LABEL_KIND (insn))
+    {
+    case LABEL_WEAK_ENTRY:
+#ifdef ASM_WEAKEN_LABEL
+      ASM_WEAKEN_LABEL (file, name);
+#endif
+    case LABEL_GLOBAL_ENTRY:
+      targetm.asm_out.globalize_label (file, name);
+    case LABEL_STATIC_ENTRY:
+#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
+      ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
+#endif
+      ASM_OUTPUT_LABEL (file, name);
+      break;
+
+    case LABEL_NORMAL:
     default:
       abort ();
     }
 }
 
+/* Return boolean indicating if there is a NOTE_INSN_UNLIKELY_EXECUTED_CODE
+   note in the instruction chain (going forward) between the current
+   instruction, and the next 'executable' instruction.  */
+
+bool
+scan_ahead_for_unlikely_executed_note (rtx insn)
+{
+  rtx temp;
+  int bb_note_count = 0;
+
+  for (temp = insn; temp; temp = NEXT_INSN (temp))
+    {
+      if (GET_CODE (temp) == NOTE
+         && NOTE_LINE_NUMBER (temp) == NOTE_INSN_UNLIKELY_EXECUTED_CODE)
+       return true;
+      if (GET_CODE (temp) == NOTE
+         && NOTE_LINE_NUMBER (temp) == NOTE_INSN_BASIC_BLOCK)
+       {
+         bb_note_count++;
+         if (bb_note_count > 1)
+           return false;
+       }
+      if (INSN_P (temp))
+       return false;
+    }
+  
+  return false;
+}
+
 /* The final scan for one insn, INSN.
    Args are same as in `final', except that INSN
    is the insn being scanned.
    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 (insn, file, optimize, prescan, nopeepholes)
-     rtx insn;
-     FILE *file;
-     int optimize ATTRIBUTE_UNUSED;
-     int prescan;
-     int nopeepholes ATTRIBUTE_UNUSED;
+final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
+                int prescan, int nopeepholes ATTRIBUTE_UNUSED,
+                int *seen)
 {
 #ifdef HAVE_cc0
   rtx set;
@@ -1886,23 +1699,54 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
        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_RANGE_BEG:
-       case NOTE_INSN_RANGE_END:
-       case NOTE_INSN_LIVE:
        case NOTE_INSN_EXPECTED_VALUE:
          break;
 
+       case NOTE_INSN_UNLIKELY_EXECUTED_CODE:
+         
+         /* 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.  */
+         
+         unlikely_text_section ();
+         break;
+         
        case NOTE_INSN_BASIC_BLOCK:
+         
+         /* If we are performing the optimization that partitions
+            basic blocks into hot & cold sections of the .o file,
+            then at the start of each new basic block, before
+            beginning to write code for the basic block, we need to
+            check to see whether the basic block belongs in the hot
+            or cold section of the .o file, and change the section we
+            are writing to appropriately.  */
+         
+         if (flag_reorder_blocks_and_partition
+             && in_unlikely_text_section()
+             && !scan_ahead_for_unlikely_executed_note (insn))
+           text_section ();
+
 #ifdef IA64_UNWIND_INFO
          IA64_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:
@@ -1916,17 +1760,35 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
          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);
+         (*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:
@@ -1979,57 +1841,16 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
          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 ();
-
-         /* This note is a line-number.  */
-         {
-           rtx note;
-           int note_after = 0;
-
-           /* If there is anything real after this note, output it.
-              If another line note follows, omit this one.  */
-           for (note = NEXT_INSN (insn); note; note = NEXT_INSN (note))
-             {
-               if (GET_CODE (note) != NOTE && GET_CODE (note) != CODE_LABEL)
-                 break;
-
-               /* These types of notes can be significant
-                  so make sure the preceding line number stays.  */
-               else if (GET_CODE (note) == NOTE
-                        && (NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_BEG
-                            || NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_END
-                            || NOTE_LINE_NUMBER (note) == NOTE_INSN_FUNCTION_BEG))
-                 break;
-               else if (GET_CODE (note) == NOTE && NOTE_LINE_NUMBER (note) > 0)
-                 {
-                   /* Another line note follows; we can delete this note
-                      if no intervening line numbers have notes elsewhere.  */
-                   int num;
-                   for (num = NOTE_LINE_NUMBER (insn) + 1;
-                        num < NOTE_LINE_NUMBER (note);
-                        num++)
-                     if (line_note_exists[num])
-                       break;
-
-                   if (num >= NOTE_LINE_NUMBER (note))
-                     note_after = 1;
-                   break;
-                 }
-             }
-
-           /* Output this line note if it is the first or the last line
-              note in a row.  */
-           if (!note_after)
-             {
-               notice_source_line (insn);
-               (*debug_hooks->source_line) (last_linenum, last_filename);
-             }
-         }
          break;
        }
       break;
@@ -2056,8 +1877,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
              ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
 #else
+#ifdef ASM_OUTPUT_ALIGN_WITH_NOP
+              ASM_OUTPUT_ALIGN_WITH_NOP (file, align);
+#else
              ASM_OUTPUT_ALIGN (file, align);
 #endif
+#endif
            }
        }
 #ifdef HAVE_cc0
@@ -2089,15 +1914,31 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 #endif
       if (prescan > 0)
        break;
-      new_block = 1;
-
-#ifdef FINAL_PRESCAN_LABEL
-      FINAL_PRESCAN_INSN (insn, NULL, 0);
-#endif
 
       if (LABEL_NAME (insn))
        (*debug_hooks->label) (insn);
 
+      /* If we are doing the optimization that partitions hot & cold
+        basic blocks into separate sections of the .o file, we need
+        to ensure the jump table ends up in the correct section...  */
+      
+      if (flag_reorder_blocks_and_partition)
+       {
+         rtx tmp_table, tmp_label;
+         if (GET_CODE (insn) == CODE_LABEL
+             && tablejump_p (NEXT_INSN (insn), &tmp_label, &tmp_table))
+           {
+             /* Do nothing; Do NOT change the current section.  */
+           }
+         else if (scan_ahead_for_unlikely_executed_note (insn)) 
+           unlikely_text_section ();
+         else 
+           {
+             if (in_unlikely_text_section ())
+               text_section ();
+           }
+       }
+
       if (app_on)
        {
          fputs (ASM_APP_OFF, file);
@@ -2140,19 +1981,16 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
              ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
                                     NEXT_INSN (insn));
 #else
-             if (LABEL_ALTERNATE_NAME (insn))
-               ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn);
-             else
-               ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
+             targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
 #endif
 #endif
              break;
            }
        }
-      if (LABEL_ALTERNATE_NAME (insn))
-       ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn);
+      if (LABEL_ALT_ENTRY_P (insn))
+       output_alternate_entry_point (file, insn);
       else
-       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
+       targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
       break;
 
     default:
@@ -2165,7 +2003,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
        /* 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;
 
@@ -2255,6 +2093,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
            break;
          }
+       /* Output this line note if it is the first or the last line
+          note in a row.  */
+       if (notice_source_line (insn))
+         {
+           (*debug_hooks->source_line) (last_linenum, last_filename);
+         }
 
        if (GET_CODE (body) == ASM_INPUT)
          {
@@ -2281,7 +2125,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
        if (asm_noperands (body) >= 0)
          {
            unsigned int noperands = asm_noperands (body);
-           rtx *ops = (rtx *) alloca (noperands * sizeof (rtx));
+           rtx *ops = alloca (noperands * sizeof (rtx));
            const char *string;
 
            /* There's no telling what that did to the condition codes.  */
@@ -2295,6 +2139,10 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
            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])
              {
@@ -2326,12 +2174,20 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
              break;
            final_sequence = body;
 
+           /* Record the delay slots' frame information before the branch.
+              This is needed for delayed calls: see execute_cfa_program().  */
+#if defined (DWARF2_UNWIND_INFO)
+           if (dwarf2out_do_frame ())
+             for (i = 1; i < XVECLEN (body, 0); i++)
+               dwarf2out_frame_debug (XVECEXP (body, 0, i));
+#endif
+
            /* The first insn in this SEQUENCE might be a JUMP_INSN that will
               force the restoration of a comparison that was previously
               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, prescan, 1, seen);
            if (next != XVECEXP (body, 0, 1))
              {
                final_sequence = 0;
@@ -2345,7 +2201,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
                /* 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, prescan, 1, seen);
                while (insn != next);
              }
 #ifdef DBR_OUTPUT_SEQEND
@@ -2382,10 +2238,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
        if (optimize)
          {
-#if 0
-           rtx set = single_set (insn);
-#endif
-
            if (set
                && GET_CODE (SET_DEST (set)) == CC0
                && insn != last_ignored_compare)
@@ -2407,7 +2259,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
                        && rtx_equal_p (SET_SRC (set), cc_status.value2)))
                  {
                    /* Don't delete insn if it has an addressing side-effect.  */
-                   if (! FIND_REG_INC_NOTE (insn, 0)
+                   if (! FIND_REG_INC_NOTE (insn, NULL_RTX)
                        /* or if anything in it is volatile.  */
                        && ! volatile_refs_p (PATTERN (insn)))
                      {
@@ -2428,8 +2280,8 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
        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
+           && REG_P (SET_SRC (body))
+           && REG_P (SET_DEST (body))
            && REGNO (SET_SRC (body)) == REGNO (SET_DEST (body)))
          break;
 #endif
@@ -2445,7 +2297,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
            && 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))) == '<'
+           && COMPARISON_P (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.  */
@@ -2553,7 +2405,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
                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, prescan, nopeepholes, seen);
 
                /* In case this is prescan, put the notes
                   in proper position for later rescan.  */
@@ -2579,13 +2431,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
        insn_code_number = recog_memoized (insn);
        cleanup_subreg_operands (insn);
 
-       /* Dump the insn in the assembly for debugging.  */
-       if (flag_dump_rtl_in_asm)
-         {
-           print_rtx_head = ASM_COMMENT_START;
-           print_rtl_single (asm_out_file, insn);
-           print_rtx_head = "";
-         }
+       /* Dump the insn in the assembly for debugging.  */
+       if (flag_dump_rtl_in_asm)
+         {
+           print_rtx_head = ASM_COMMENT_START;
+           print_rtl_single (asm_out_file, insn);
+           print_rtx_head = "";
+         }
 
        if (! constrain_operands_cached (1))
          fatal_insn_not_found (insn);
@@ -2634,7 +2486,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
            if (prev_nonnote_insn (insn) != last_ignored_compare)
              abort ();
-           new_block = 0;
 
            /* We have already processed the notes between the setter and
               the user.  Make sure we don't process them again, this is
@@ -2668,7 +2519,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
            abort ();
 #endif
 
-           new_block = 0;
            return new;
          }
 
@@ -2682,22 +2532,23 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
        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 defined (HAVE_prologue)
-       if (GET_CODE (insn) == INSN && dwarf2out_do_frame ())
-         dwarf2out_frame_debug (insn);
-#else
-       if (!ACCUMULATE_OUTGOING_ARGS
-           && GET_CODE (insn) == INSN
+       if (GET_CODE (insn) == INSN
+#if !defined (HAVE_prologue)
+           && !ACCUMULATE_OUTGOING_ARGS
+#endif
+           && final_sequence == 0
            && dwarf2out_do_frame ())
          dwarf2out_frame_debug (insn);
 #endif
-#endif
 
 #if 0
-       /* It's not at all clear why we did this and doing so interferes
-          with tests we'd like to do to use REG_WAS_0 notes, so let's try
-          with this out.  */
+       /* 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;
@@ -2705,9 +2556,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
        /* Emit information for vtable gc.  */
        note = find_reg_note (insn, REG_VTABLE_REF, NULL_RTX);
-       if (note)
-         assemble_vtable_entry (XEXP (XEXP (note, 0), 0),
-                                INTVAL (XEXP (XEXP (note, 0), 1)));
 
        current_output_insn = debug_insn = 0;
       }
@@ -2718,34 +2566,43 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 /* Output debugging info to the assembler file FILE
    based on the NOTE-insn INSN, assumed to be a line number.  */
 
-static void
-notice_source_line (insn)
-     rtx insn;
+static bool
+notice_source_line (rtx insn)
 {
-  const char *filename = NOTE_SOURCE_FILE (insn);
+  const char *filename = insn_file (insn);
+  int linenum = insn_line (insn);
 
-  last_filename = filename;
-  last_linenum = NOTE_LINE_NUMBER (insn);
-  high_block_linenum = MAX (last_linenum, high_block_linenum);
-  high_function_linenum = MAX (last_linenum, high_function_linenum);
+  if (filename && (filename != last_filename || last_linenum != linenum))
+    {
+      last_filename = filename;
+      last_linenum = linenum;
+      high_block_linenum = MAX (last_linenum, high_block_linenum);
+      high_function_linenum = MAX (last_linenum, high_function_linenum);
+      return true;
+    }
+  return false;
 }
 \f
 /* For each operand in INSN, simplify (subreg (reg)) so that it refers
    directly to the desired hard register.  */
 
 void
-cleanup_subreg_operands (insn)
-     rtx insn;
+cleanup_subreg_operands (rtx insn)
 {
   int i;
   extract_insn_cached (insn);
   for (i = 0; i < recog_data.n_operands; i++)
     {
-      if (GET_CODE (recog_data.operand[i]) == SUBREG)
+      /* The following test cannot use recog_data.operand when testing
+        for a SUBREG: the underlying object might have been changed
+        already if we are inside a match_operator expression that
+        matches the else clause.  Instead we test the underlying
+        expression directly.  */
+      if (GET_CODE (*recog_data.operand_loc[i]) == SUBREG)
        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]);
     }
 
@@ -2755,7 +2612,7 @@ cleanup_subreg_operands (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]);
     }
 }
@@ -2764,15 +2621,14 @@ cleanup_subreg_operands (insn)
    based on the thing it is a subreg of.  */
 
 rtx
-alter_subreg (xp)
-     rtx *xp;
+alter_subreg (rtx *xp)
 {
   rtx x = *xp;
   rtx y = SUBREG_REG (x);
 
   /* simplify_subreg does not remove subreg from volatile references.
      We are required to.  */
-  if (GET_CODE (y) == MEM)
+  if (MEM_P (y))
     *xp = adjust_address (y, GET_MODE (x), SUBREG_BYTE (x));
   else
     {
@@ -2782,14 +2638,10 @@ alter_subreg (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))
        {
-         REGNO (x) = subreg_hard_regno (x, 1);
-         PUT_CODE (x, REG);
-         ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y);
-         /* This field has a different meaning for REGs and SUBREGs.  Make
-            sure to clear it!  */
-         x->used = 0;
+         unsigned int regno = subreg_hard_regno (x, 1);
+         *xp = gen_rtx_REG_offset (y, GET_MODE (x), regno, SUBREG_BYTE (x));
        }
       else
        abort ();
@@ -2801,8 +2653,7 @@ alter_subreg (xp)
 /* Do alter_subreg on all the SUBREGs contained in X.  */
 
 static rtx
-walk_alter_subreg (xp)
-     rtx *xp;
+walk_alter_subreg (rtx *xp)
 {
   rtx x = *xp;
   switch (GET_CODE (x))
@@ -2839,8 +2690,7 @@ walk_alter_subreg (xp)
    2 means that COND has been altered.  */
 
 static int
-alter_cond (cond)
-     rtx cond;
+alter_cond (rtx cond)
 {
   int value = 0;
 
@@ -2993,13 +2843,27 @@ alter_cond (cond)
    In an `asm', it's the user's fault; otherwise, the compiler's fault.  */
 
 void
-output_operand_lossage (msgid)
-     const char *msgid;
+output_operand_lossage (const char *msgid, ...)
 {
+  char *fmt_string;
+  char *new_message;
+  const char *pfx_str;
+  va_list ap;
+
+  va_start (ap, msgid);
+
+  pfx_str = this_is_asm_operands ? _("invalid `asm': ") : "output_operand: ";
+  asprintf (&fmt_string, "%s%s", pfx_str, _(msgid));
+  vasprintf (&new_message, fmt_string, ap);
+
   if (this_is_asm_operands)
-    error_for_asm (this_is_asm_operands, "invalid `asm': %s", _(msgid));
+    error_for_asm (this_is_asm_operands, "%s", new_message);
   else
-    internal_error ("output_operand: %s", _(msgid));
+    internal_error ("%s", new_message);
+
+  free (fmt_string);
+  free (new_message);
+  va_end (ap);
 }
 \f
 /* Output of assembler code from a template, and its subroutines.  */
@@ -3008,7 +2872,7 @@ output_operand_lossage (msgid)
    alternative used.  */
 
 static void
-output_asm_name ()
+output_asm_name (void)
 {
   if (debug_insn)
     {
@@ -3033,18 +2897,16 @@ output_asm_name ()
    corresponds to the address of the object and 0 if to the object.  */
 
 static tree
-get_mem_expr_from_op (op, paddressp)
-     rtx op;
-     int *paddressp;
+get_mem_expr_from_op (rtx op, int *paddressp)
 {
   tree expr;
   int inner_addressp;
 
   *paddressp = 0;
 
-  if (GET_CODE (op) == REG && ORIGINAL_REGNO (op) >= FIRST_PSEUDO_REGISTER)
-    return REGNO_DECL (ORIGINAL_REGNO (op));
-  else if (GET_CODE (op) != MEM)
+  if (REG_P (op))
+    return REG_EXPR (op);
+  else if (!MEM_P (op))
     return 0;
 
   if (MEM_EXPR (op) != 0)
@@ -3063,23 +2925,20 @@ get_mem_expr_from_op (op, 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);
   return inner_addressp ? 0 : expr;
 }
-  
+
 /* Output operand names for assembler instructions.  OPERANDS is the
    operand vector, OPORDER is the order to write the operands, and NOPS
    is the number of operands to write.  */
 
 static void
-output_asm_operand_names (operands, oporder, nops)
-     rtx *operands;
-     int *oporder;
-     int nops;
+output_asm_operand_names (rtx *operands, int *oporder, int nops)
 {
   int wrote = 0;
   int i;
@@ -3087,16 +2946,22 @@ output_asm_operand_names (operands, oporder, nops)
   for (i = 0; i < nops; i++)
     {
       int addressp;
-      tree expr = get_mem_expr_from_op (operands[oporder[i]], &addressp);
+      rtx op = operands[oporder[i]];
+      tree expr = get_mem_expr_from_op (op, &addressp);
 
+      fprintf (asm_out_file, "%c%s",
+              wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START);
+      wrote = 1;
       if (expr)
        {
-         fprintf (asm_out_file, "%c%s %s",
-                  wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START,
+         fprintf (asm_out_file, "%s",
                   addressp ? "*" : "");
          print_mem_expr (asm_out_file, expr);
          wrote = 1;
        }
+      else if (REG_P (op) && ORIGINAL_REGNO (op)
+              && ORIGINAL_REGNO (op) != REGNO (op))
+       fprintf (asm_out_file, " tmp%i", ORIGINAL_REGNO (op));
     }
 }
 
@@ -3117,9 +2982,7 @@ output_asm_operand_names (operands, oporder, nops)
       of the operand, with no other punctuation.  */
 
 void
-output_asm_insn (template, operands)
-     const char *template;
-     rtx *operands;
+output_asm_insn (const char *template, rtx *operands)
 {
   const char *p;
   int c;
@@ -3204,7 +3067,7 @@ output_asm_insn (template, operands)
                    output_operand_lossage ("unterminated assembly dialect alternative");
                    break;
                  }
-             }   
+             }
            while (*p++ != '}');
            dialect = 0;
          }
@@ -3245,7 +3108,7 @@ output_asm_insn (template, operands)
            c = atoi (p);
 
            if (! ISDIGIT (*p))
-             output_operand_lossage ("operand number missing after %-letter");
+             output_operand_lossage ("operand number missing after %%-letter");
            else if (this_is_asm_operands
                     && (c < 0 || (unsigned int) c >= insn_noperands))
              output_operand_lossage ("operand number out of range");
@@ -3325,8 +3188,7 @@ output_asm_insn (template, operands)
 /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol.  */
 
 void
-output_asm_label (x)
-     rtx x;
+output_asm_label (rtx x)
 {
   char buf[256];
 
@@ -3337,7 +3199,7 @@ output_asm_label (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);
 }
@@ -3353,9 +3215,7 @@ output_asm_label (x)
    by PRINT_OPERAND.  */
 
 static void
-output_operand (x, code)
-     rtx x;
-     int code ATTRIBUTE_UNUSED;
+output_operand (rtx x, int code ATTRIBUTE_UNUSED)
 {
   if (x && GET_CODE (x) == SUBREG)
     x = alter_subreg (&x);
@@ -3363,7 +3223,7 @@ output_operand (x, code)
   /* 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)
+  if (x && REG_P (x) && REGNO (x) >= FIRST_PSEUDO_REGISTER)
     abort ();
 
   PRINT_OPERAND (asm_out_file, x, code);
@@ -3374,8 +3234,7 @@ output_operand (x, code)
    The macro PRINT_OPERAND_ADDRESS exists just to control this function.  */
 
 void
-output_address (x)
-     rtx x;
+output_address (rtx x)
 {
   walk_alter_subreg (&x);
   PRINT_OPERAND_ADDRESS (asm_out_file, x);
@@ -3386,9 +3245,7 @@ output_address (x)
    that may appear in these expressions.  */
 
 void
-output_addr_const (file, x)
-     FILE *file;
-     rtx x;
+output_addr_const (FILE *file, rtx x)
 {
   char buf[256];
 
@@ -3400,6 +3257,8 @@ output_addr_const (file, x)
       break;
 
     case SYMBOL_REF:
+      if (SYMBOL_REF_DECL (x))
+       mark_decl_referenced (SYMBOL_REF_DECL (x));
 #ifdef ASM_OUTPUT_SYMBOL_REF
       ASM_OUTPUT_SYMBOL_REF (file, x);
 #else
@@ -3475,20 +3334,21 @@ output_addr_const (file, x)
 
       output_addr_const (file, XEXP (x, 0));
       fprintf (file, "-");
-      if ((GET_CODE (XEXP (x, 1)) == CONST_INT
-          && INTVAL (XEXP (x, 1)) < 0)
-         || GET_CODE (XEXP (x, 1)) != CONST_INT)
+      if ((GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0)
+         || GET_CODE (XEXP (x, 1)) == PC
+         || GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
+       output_addr_const (file, XEXP (x, 1));
+      else
        {
          fputs (targetm.asm_out.open_paren, file);
          output_addr_const (file, XEXP (x, 1));
          fputs (targetm.asm_out.close_paren, file);
        }
-      else
-       output_addr_const (file, XEXP (x, 1));
       break;
 
     case ZERO_EXTEND:
     case SIGN_EXTEND:
+    case SUBREG:
       output_addr_const (file, XEXP (x, 0));
       break;
 
@@ -3509,19 +3369,18 @@ output_addr_const (file, x)
    %U prints the value of USER_LABEL_PREFIX.
    %I prints the value of IMMEDIATE_PREFIX.
    %O runs ASM_OUTPUT_OPCODE to transform what follows in the string.
-   Also supported are %d, %x, %s, %e, %f, %g and %%.
+   Also supported are %d, %i, %u, %x, %X, %o, %c, %s and %%.
 
    We handle alternate assembler dialects here, just like output_asm_insn.  */
 
 void
-asm_fprintf VPARAMS ((FILE *file, const char *p, ...))
+asm_fprintf (FILE *file, const char *p, ...)
 {
   char buf[10];
   char *q, c;
+  va_list argptr;
 
-  VA_OPEN (argptr, p);
-  VA_FIXEDARG (argptr, FILE *, file);
-  VA_FIXEDARG (argptr, const char *, p);
+  va_start (argptr, p);
 
   buf[0] = '%';
 
@@ -3559,6 +3418,11 @@ asm_fprintf VPARAMS ((FILE *file, const char *p, ...))
       case '%':
        c = *p++;
        q = &buf[1];
+       while (strchr ("-+ #0", c))
+         {
+           *q++ = c;
+           c = *p++;
+         }
        while (ISDIGIT (c) || c == '.')
          {
            *q++ = c;
@@ -3567,32 +3431,24 @@ asm_fprintf VPARAMS ((FILE *file, const char *p, ...))
        switch (c)
          {
          case '%':
-           fprintf (file, "%%");
+           putc ('%', file);
            break;
 
          case 'd':  case 'i':  case 'u':
-         case 'x':  case 'p':  case 'X':
-         case 'o':
+         case 'x':  case 'X':  case 'o':
+         case 'c':
            *q++ = c;
            *q = 0;
            fprintf (file, buf, va_arg (argptr, int));
            break;
 
          case 'w':
-           /* This is a prefix to the 'd', 'i', 'u', 'x', 'p', and 'X' cases,
-              but we do not check for those cases.  It means that the value
-              is a HOST_WIDE_INT, which may be either `int' or `long'.  */
-
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
-#else
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
-           *q++ = 'l';
-#else
-           *q++ = 'l';
-           *q++ = 'l';
-#endif
-#endif
-
+           /* This is a prefix to the 'd', 'i', 'u', 'x', 'X', and
+              'o' cases, but we do not check for those cases.  It
+              means that the value is a HOST_WIDE_INT, which may be
+              either `long' or `long long'.  */
+           memcpy (q, HOST_WIDE_INT_PRINT, strlen (HOST_WIDE_INT_PRINT));
+           q += strlen (HOST_WIDE_INT_PRINT);
            *q++ = *p++;
            *q = 0;
            fprintf (file, buf, va_arg (argptr, HOST_WIDE_INT));
@@ -3600,17 +3456,22 @@ asm_fprintf VPARAMS ((FILE *file, const char *p, ...))
 
          case 'l':
            *q++ = c;
-           *q++ = *p++;
-           *q = 0;
-           fprintf (file, buf, va_arg (argptr, long));
-           break;
+#ifdef HAVE_LONG_LONG
+           if (*p == 'l')
+             {
+               *q++ = *p++;
+               *q++ = *p++;
+               *q = 0;
+               fprintf (file, buf, va_arg (argptr, long long));
+             }
+           else
+#endif
+             {
+               *q++ = *p++;
+               *q = 0;
+               fprintf (file, buf, va_arg (argptr, long));
+             }
 
-         case 'e':
-         case 'f':
-         case 'g':
-           *q++ = c;
-           *q = 0;
-           fprintf (file, buf, va_arg (argptr, double));
            break;
 
          case 's':
@@ -3648,7 +3509,7 @@ asm_fprintf VPARAMS ((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
@@ -3667,9 +3528,9 @@ asm_fprintf VPARAMS ((FILE *file, const char *p, ...))
        break;
 
       default:
-       fputc (c, file);
+       putc (c, file);
       }
-  VA_CLOSE (argptr);
+  va_end (argptr);
 }
 \f
 /* Split up a CONST_DOUBLE or integer constant rtx
@@ -3678,9 +3539,7 @@ asm_fprintf VPARAMS ((FILE *file, const char *p, ...))
    and in *SECOND the other.  */
 
 void
-split_double (value, first, second)
-     rtx value;
-     rtx *first, *second;
+split_double (rtx value, rtx *first, rtx *second)
 {
   if (GET_CODE (value) == CONST_INT)
     {
@@ -3785,7 +3644,6 @@ split_double (value, first, second)
     }
   else
     {
-#ifdef REAL_ARITHMETIC
       REAL_VALUE_TYPE r;
       long l[2];
       REAL_VALUE_FROM_CONST_DOUBLE (r, value);
@@ -3814,42 +3672,18 @@ split_double (value, first, second)
 
       *first = GEN_INT ((HOST_WIDE_INT) l[0]);
       *second = GEN_INT ((HOST_WIDE_INT) l[1]);
-#else
-      if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
-          || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
-         && ! flag_pretend_float)
-       abort ();
-
-      if (
-#ifdef HOST_WORDS_BIG_ENDIAN
-         WORDS_BIG_ENDIAN
-#else
-         ! WORDS_BIG_ENDIAN
-#endif
-         )
-       {
-         /* Host and target agree => no need to swap.  */
-         *first = GEN_INT (CONST_DOUBLE_LOW (value));
-         *second = GEN_INT (CONST_DOUBLE_HIGH (value));
-       }
-      else
-       {
-         *second = GEN_INT (CONST_DOUBLE_LOW (value));
-         *first = GEN_INT (CONST_DOUBLE_HIGH (value));
-       }
-#endif /* no REAL_ARITHMETIC */
     }
 }
 \f
 /* Return nonzero if this function has no function calls.  */
 
 int
-leaf_function_p ()
+leaf_function_p (void)
 {
   rtx insn;
   rtx link;
 
-  if (profile_flag || profile_arc_flag)
+  if (current_function_profile || profile_arc_flag)
     return 0;
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
@@ -3882,13 +3716,12 @@ leaf_function_p ()
   return 1;
 }
 
-/* Return 1 if branch is an forward branch.
+/* Return 1 if branch is a forward branch.
    Uses insn_shuid array, so it works only in the final pass.  May be used by
    output templates to customary add branch prediction hints.
  */
 int
-final_forward_branch_p (insn)
-     rtx insn;
+final_forward_branch_p (rtx insn)
 {
   int insn_id, label_id;
   if (!uid_shuid)
@@ -3916,10 +3749,10 @@ final_forward_branch_p (insn)
    safely renumbered.  */
 
 int
-only_leaf_regs_used ()
+only_leaf_regs_used (void)
 {
   int i;
-  char *permitted_reg_in_leaf_functions = LEAF_REGISTERS;
+  const char *const permitted_reg_in_leaf_functions = LEAF_REGISTERS;
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     if ((regs_ever_live[i] || global_regs[i])
@@ -3928,7 +3761,7 @@ only_leaf_regs_used ()
 
   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;
 
@@ -3939,8 +3772,7 @@ only_leaf_regs_used ()
    available in leaf functions.  */
 
 static void
-leaf_renumber_regs (first)
-     rtx first;
+leaf_renumber_regs (rtx first)
 {
   rtx insn;
 
@@ -3961,8 +3793,7 @@ leaf_renumber_regs (first)
    available in leaf functions.  */
 
 void
-leaf_renumber_regs_insn (in_rtx)
-     rtx in_rtx;
+leaf_renumber_regs_insn (rtx in_rtx)
 {
   int i, j;
   const char *format_ptr;
@@ -3974,7 +3805,7 @@ leaf_renumber_regs_insn (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;
 
@@ -4039,3 +3870,85 @@ leaf_renumber_regs_insn (in_rtx)
       }
 }
 #endif
+
+
+/* When -gused is used, emit debug info for only used symbols. But in
+   addition to the standard intercepted debug_hooks there are some direct
+   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 an intercept nesting counter (debug_nesting). We only save the
+   intercepted arguments if the nesting is 1.  */
+int debug_nesting = 0;
+
+static tree *symbol_queue;
+int symbol_queue_index = 0;
+static int symbol_queue_size = 0;
+
+/* Generate the symbols for any queued up type symbols we encountered
+   while generating the type info for some originally used symbol.
+   This might generate additional entries in the queue.  Only when
+   the nesting depth goes to 0 is this routine called.  */
+
+void
+debug_flush_symbol_queue (void)
+{
+  int i;
+
+  /* Make sure that additionally queued items are not flushed
+     prematurely.  */
+
+  ++debug_nesting;
+
+  for (i = 0; i < symbol_queue_index; ++i)
+    {
+      /* If we pushed queued symbols then such symbols are must be
+         output no matter what anyone else says.  Specifically,
+         we need to make sure dbxout_symbol() thinks the symbol was
+         used and also we need to override TYPE_DECL_SUPPRESS_DEBUG
+         which may be set for outside reasons.  */
+      int saved_tree_used = TREE_USED (symbol_queue[i]);
+      int saved_suppress_debug = TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]);
+      TREE_USED (symbol_queue[i]) = 1;
+      TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = 0;
+
+#ifdef DBX_DEBUGGING_INFO
+      dbxout_symbol (symbol_queue[i], 0);
+#endif
+
+      TREE_USED (symbol_queue[i]) = saved_tree_used;
+      TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = saved_suppress_debug;
+    }
+
+  symbol_queue_index = 0;
+  --debug_nesting;
+}
+
+/* Queue a type symbol needed as part of the definition of a decl
+   symbol.  These symbols are generated when debug_flush_symbol_queue()
+   is called.  */
+
+void
+debug_queue_symbol (tree decl)
+{
+  if (symbol_queue_index >= symbol_queue_size)
+    {
+      symbol_queue_size += 10;
+      symbol_queue = xrealloc (symbol_queue,
+                              symbol_queue_size * sizeof (tree));
+    }
+
+  symbol_queue[symbol_queue_index++] = decl;
+}
+
+/* Free symbol queue.  */
+void
+debug_free_queue (void)
+{
+  if (symbol_queue)
+    {
+      free (symbol_queue);
+      symbol_queue = NULL;
+      symbol_queue_size = 0;
+    }
+}