OSDN Git Service

* doc/install.texi (xtensa-*-elf): New target.
[pf3gnuchains/gcc-fork.git] / gcc / final.c
index 38ec173..ec3b1c7 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 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -67,6 +67,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "basic-block.h"
 #include "target.h"
 #include "debug.h"
+#include "expr.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"          /* Needed for external data
@@ -113,10 +114,6 @@ static int high_function_linenum;
 /* Filename of last NOTE.  */
 static const char *last_filename;
 
-/* Number of basic blocks seen so far;
-   used if profile_block_flag is set.  */
-static int count_basic_blocks;
-
 /* Number of instrumented arcs when profile_arc_flag is set.  */
 extern int count_instrumented_edges;
 
@@ -205,45 +202,16 @@ static char *line_note_exists;
 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 add_bb             PARAMS ((FILE *));
-static int add_bb_string       PARAMS ((const char *, int));
 static void notice_source_line PARAMS ((rtx));
-static rtx walk_alter_subreg   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));
 #ifdef LEAF_REGISTERS
 static void leaf_renumber_regs PARAMS ((rtx));
@@ -279,24 +247,17 @@ void
 end_final (filename)
      const char *filename;
 {
-  int i;
-
-  if (profile_block_flag || profile_arc_flag)
+  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;
 
-      if (profile_block_flag)
-       size = long_bytes * count_basic_blocks;
-      else
-       size = gcov_type_bytes * count_instrumented_edges;
+      size = gcov_type_bytes * count_instrumented_edges;
       rounded = size;
 
       rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
@@ -344,53 +305,24 @@ end_final (filename)
       assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
                        align2, 1);
 
-      /* Count of the # of basic blocks or # of instrumented arcs.  */
-      assemble_integer (GEN_INT (profile_block_flag
-                                ? count_basic_blocks
-                                : count_instrumented_edges),
+      /* 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);
 
-      /* address of basic block start address table */
-      if (profile_block_flag)
-       {
-         ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
-         assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
-                           pointer_bytes, align2, 1);
-       }
-      else
-       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.  */
-      if (profile_block_flag)
-       {
-         ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 4);
-         assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
-                           pointer_bytes, align2, 1);
-       }
-      else
-       assemble_integer (const0_rtx, pointer_bytes, align2, 1);
+      assemble_integer (const0_rtx, pointer_bytes, align2, 1);
 
       /* Address of line number and filename tables if debugging.  */
-      if (write_symbols != NO_DEBUG && profile_block_flag)
-       {
-         ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 5);
-         assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
-                           pointer_bytes, align2, 1);
-         ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 6);
-         assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
-                           pointer_bytes, align2, 1);
-       }
-      else
-       {
-         assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-         assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-       }
+      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);
@@ -407,10 +339,7 @@ end_final (filename)
        strcat (data_file, "/");
        strcat (data_file, filename);
        strip_off_ending (data_file, len);
-       if (profile_block_flag)
-         strcat (data_file, ".d");
-       else
-         strcat (data_file, ".da");
+       strcat (data_file, ".da");
        assemble_string (data_file, strlen (data_file) + 1);
       }
 
@@ -443,95 +372,6 @@ end_final (filename)
 #endif
 #endif
        }
-
-      /* Output any basic block strings */
-      if (profile_block_flag)
-       {
-         readonly_data_section ();
-         if (sbb_head)
-           {
-             ASM_OUTPUT_ALIGN (asm_out_file, align);
-             for (sptr = sbb_head; sptr != 0; sptr = sptr->next)
-               {
-                 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBC",
-                                            sptr->label_num);
-                 assemble_string (sptr->string, sptr->length);
-               }
-           }
-       }
-
-      /* Output the table of addresses.  */
-      if (profile_block_flag)
-       {
-         /* Realign in new section */
-         ASM_OUTPUT_ALIGN (asm_out_file, align);
-         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 3);
-         for (i = 0; i < count_basic_blocks; i++)
-           {
-             ASM_GENERATE_INTERNAL_LABEL (name, "LPB", i);
-             assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
-                               pointer_bytes, align2, 1);
-           }
-       }
-
-      /* Output the table of function names.  */
-      if (profile_block_flag)
-       {
-         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 4);
-         for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++)
-           {
-             if (ptr->func_label_num >= 0)
-               {
-                 ASM_GENERATE_INTERNAL_LABEL (name, "LPBC",
-                                              ptr->func_label_num);
-                 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
-                                   pointer_bytes, align2, 1);
-               }
-             else
-               assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-           }
-
-         for (; i < count_basic_blocks; i++)
-           assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-       }
-
-      if (write_symbols != NO_DEBUG && profile_block_flag)
-       {
-         /* Output the table of line numbers.  */
-         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 5);
-         for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++)
-           assemble_integer (GEN_INT (ptr->line_num), long_bytes, align2, 1);
-
-         for (; i < count_basic_blocks; i++)
-           assemble_integer (const0_rtx, long_bytes, align2, 1);
-
-         /* Output the table of file names.  */
-         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 6);
-         for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++)
-           {
-             if (ptr->file_label_num >= 0)
-               {
-                 ASM_GENERATE_INTERNAL_LABEL (name, "LPBC",
-                                              ptr->file_label_num);
-                 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
-                                   pointer_bytes, align2, 1);
-               }
-             else
-               assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-           }
-
-         for (; i < count_basic_blocks; i++)
-           assemble_integer (const0_rtx, pointer_bytes, align2, 1);
-       }
-
-      /* End with the address of the table of addresses,
-        so we can find it easily, as the last word in the file's text.  */
-      if (profile_block_flag)
-       {
-         ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
-         assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
-                           pointer_bytes, align2, 1);
-       }
     }
 }
 
@@ -600,7 +440,7 @@ dbr_sequence_length ()
 /* Arrays for insn lengths, and addresses.  The latter is referenced by
    `insn_current_length'.  */
 
-static short *insn_lengths;
+static int *insn_lengths;
 
 #ifdef HAVE_ATTR_length
 varray_type insn_addresses_;
@@ -615,7 +455,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)]
@@ -773,7 +613,7 @@ get_attr_length (insn)
 #endif
 
 #ifndef LABEL_ALIGN_MAX_SKIP
-#define LABEL_ALIGN_MAX_SKIP (align_labels-1)
+#define LABEL_ALIGN_MAX_SKIP align_labels_max_skip
 #endif
 
 #ifndef LOOP_ALIGN
@@ -781,7 +621,7 @@ get_attr_length (insn)
 #endif
 
 #ifndef LOOP_ALIGN_MAX_SKIP
-#define LOOP_ALIGN_MAX_SKIP (align_loops-1)
+#define LOOP_ALIGN_MAX_SKIP align_loops_max_skip
 #endif
 
 #ifndef LABEL_ALIGN_AFTER_BARRIER
@@ -797,7 +637,7 @@ get_attr_length (insn)
 #endif
 
 #ifndef JUMP_ALIGN_MAX_SKIP
-#define JUMP_ALIGN_MAX_SKIP (align_jumps-1)
+#define JUMP_ALIGN_MAX_SKIP align_jumps_max_skip
 #endif
 
 #ifndef ADDR_VEC_ALIGN
@@ -857,7 +697,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
@@ -989,14 +829,14 @@ compute_alignments ()
            branch_frequency += EDGE_FREQUENCY (e);
        }
 
-      /* There are two purposes to align block with no fallthru incomming edge:
+      /* 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.
         To catch the second, we align blocks that are executed more frequently
-        than the predecesor and the predecesor is likely to not be executed
+        than the predecessor and the predecessor is likely to not be executed
         when function is called.  */
 
       if (!has_fallthru
@@ -1043,7 +883,7 @@ compute_alignments ()
    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.  */
 
@@ -1120,7 +960,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)
@@ -1183,7 +1023,7 @@ shorten_branches (first)
 #ifdef HAVE_ATTR_length
 
   /* Allocate the rest of the arrays.  */
-  insn_lengths = (short *) xmalloc (max_uid * sizeof (short));
+  insn_lengths = (int *) 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.  */
@@ -1366,7 +1206,7 @@ shorten_branches (first)
 #ifdef ADJUST_INSN_LENGTH
       ADJUST_INSN_LENGTH (insn, insn_lengths[uid]);
       if (insn_lengths[uid] < 0)
-       fatal_insn ("Negative insn length", insn);
+       fatal_insn ("negative insn length", insn);
 #endif
     }
 
@@ -1423,12 +1263,15 @@ shorten_branches (first)
              rtx rel_lab = XEXP (XEXP (body, 0), 0);
              rtx min_lab = XEXP (XEXP (body, 2), 0);
              rtx max_lab = XEXP (XEXP (body, 3), 0);
-             addr_diff_vec_flags flags = ADDR_DIFF_VEC_FLAGS (body);
              int rel_addr = INSN_ADDRESSES (INSN_UID (rel_lab));
              int min_addr = INSN_ADDRESSES (INSN_UID (min_lab));
              int max_addr = INSN_ADDRESSES (INSN_UID (max_lab));
              rtx prev;
              int rel_align = 0;
+             addr_diff_vec_flags flags;
+
+             /* Avoid automatic aggregate initialization.  */
+             flags = ADDR_DIFF_VEC_FLAGS (body);
 
              /* Try to find a known alignment for rel_lab.  */
              for (prev = rel_lab;
@@ -1672,7 +1515,7 @@ final_start_function (first, file, optimize)
   (*debug_hooks->begin_prologue) (last_linenum, last_filename);
 
 #if defined (DWARF2_UNWIND_INFO) || defined (IA64_UNWIND_INFO)
-  if (write_symbols != DWARF2_DEBUG)
+  if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG)
     dwarf2out_begin_prologue (0, NULL);
 #endif
 
@@ -1684,7 +1527,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 */
 
@@ -1709,6 +1552,12 @@ 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
+
   /* If the machine represents the prologue as RTL, the profiling code must
      be emitted when NOTE_INSN_PROLOGUE_END is scanned.  */
 #ifdef HAVE_prologue
@@ -1717,37 +1566,21 @@ final_start_function (first, file, optimize)
     profile_after_prologue (file);
 
   profile_label_no++;
-
-  /* If we are doing basic block profiling, remember a printable version
-     of the function name.  */
-  if (profile_block_flag)
-    {
-      bb_func_label_num =
-       add_bb_string ((*decl_printable_name) (current_function_decl, 2),
-                      FALSE);
-    }
 }
 
 static void
 profile_after_prologue (file)
      FILE *file ATTRIBUTE_UNUSED;
 {
-#ifdef FUNCTION_BLOCK_PROFILER
-  if (profile_block_flag)
-    {
-      FUNCTION_BLOCK_PROFILER (file, count_basic_blocks);
-    }
-#endif /* FUNCTION_BLOCK_PROFILER */
-
 #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;
+     FILE *file ATTRIBUTE_UNUSED;
 {
 #ifndef NO_PROFILE_COUNTERS
   int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
@@ -1840,94 +1673,10 @@ final_end_function ()
   (*debug_hooks->end_epilogue) ();
 
 #if defined (DWARF2_UNWIND_INFO)
-  if (write_symbols != DWARF2_DEBUG && dwarf2out_do_frame ())
+  if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG
+      && dwarf2out_do_frame ())
     dwarf2out_end_epilogue ();
 #endif
-
-  bb_func_label_num = -1;      /* not in function, nuke label # */
-}
-\f
-/* Add a block to the linked list that remembers the current line/file/function
-   for basic block profiling.  Emit the label in front of the basic block and
-   the instructions that increment the count field.  */
-
-static void
-add_bb (file)
-     FILE *file;
-{
-  struct bb_list *ptr =
-    (struct bb_list *) permalloc (sizeof (struct bb_list));
-
-  /* Add basic block to linked list.  */
-  ptr->next = 0;
-  ptr->line_num = last_linenum;
-  ptr->file_label_num = bb_file_label_num;
-  ptr->func_label_num = bb_func_label_num;
-  *bb_tail = ptr;
-  bb_tail = &ptr->next;
-
-  /* Enable the table of basic-block use counts
-     to point at the code it applies to.  */
-  ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks);
-
-  /* Before first insn of this basic block, increment the
-     count of times it was entered.  */
-#ifdef BLOCK_PROFILER
-  BLOCK_PROFILER (file, count_basic_blocks);
-#endif
-#ifdef HAVE_cc0
-  CC_STATUS_INIT;
-#endif
-
-  new_block = 0;
-  count_basic_blocks++;
-}
-
-/* Add a string to be used for basic block profiling.  */
-
-static int
-add_bb_string (string, perm_p)
-     const char *string;
-     int perm_p;
-{
-  int len;
-  struct bb_str *ptr = 0;
-
-  if (!string)
-    {
-      string = "<unknown>";
-      perm_p = TRUE;
-    }
-
-  /* Allocate a new string if the current string isn't permanent.  If
-     the string is permanent search for the same string in other
-     allocations.  */
-
-  len = strlen (string) + 1;
-  if (!perm_p)
-    {
-      char *p = (char *) permalloc (len);
-      memcpy (p, string, len);
-      string = p;
-    }
-  else
-    for (ptr = sbb_head; ptr != (struct bb_str *) 0; ptr = ptr->next)
-      if (ptr->string == string)
-       break;
-
-  /* Allocate a new string block if we need to.  */
-  if (!ptr)
-    {
-      ptr = (struct bb_str *) permalloc (sizeof (*ptr));
-      ptr->next = 0;
-      ptr->length = len;
-      ptr->label_num = sbb_label_num++;
-      ptr->string = string;
-      *sbb_tail = ptr;
-      sbb_tail = &ptr->next;
-    }
-
-  return ptr->label_num;
 }
 \f
 /* Output assembler code for some insns: all or part of a function.
@@ -2038,11 +1787,6 @@ final (first, file, optimize, prescan)
       insn = final_scan_insn (insn, file, optimize, prescan, 0);
     }
 
-  /* Do basic-block profiling here
-     if the last insn was a conditional branch.  */
-  if (profile_block_flag && new_block)
-    add_bb (file);
-
   free (line_note_exists);
   line_note_exists = NULL;
 }
@@ -2154,7 +1898,9 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
          if (debug_info_level == DINFO_LEVEL_NORMAL
              || debug_info_level == DINFO_LEVEL_VERBOSE
              || write_symbols == DWARF_DEBUG
-             || write_symbols == DWARF2_DEBUG)
+             || write_symbols == DWARF2_DEBUG
+             || write_symbols == VMS_AND_DWARF2_DEBUG
+             || write_symbols == VMS_DEBUG)
            {
              int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
 
@@ -2174,7 +1920,9 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
          if (debug_info_level == DINFO_LEVEL_NORMAL
              || debug_info_level == DINFO_LEVEL_VERBOSE
              || write_symbols == DWARF_DEBUG
-             || write_symbols == DWARF2_DEBUG)
+             || write_symbols == DWARF2_DEBUG
+             || write_symbols == VMS_AND_DWARF2_DEBUG
+             || write_symbols == VMS_DEBUG)
            {
              int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
 
@@ -2269,11 +2017,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 #endif
 
          if (align && NEXT_INSN (insn))
+           {
 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
-           ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
+             ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
 #else
-           ASM_OUTPUT_ALIGN (file, align);
+             ASM_OUTPUT_ALIGN (file, align);
 #endif
+           }
        }
 #ifdef HAVE_cc0
       CC_STATUS_INIT;
@@ -2471,11 +2221,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
            break;
          }
 
-       /* Do basic-block profiling when we reach a new block.
-          Done here to avoid jump tables.  */
-       if (profile_block_flag && new_block)
-         add_bb (file);
-
        if (GET_CODE (body) == ASM_INPUT)
          {
            const char *string = XSTR (body, 0);
@@ -2582,22 +2327,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
              {
                CC_STATUS_INIT;
              }
-
-           /* Following a conditional branch sequence, we have a new basic
-              block.  */
-           if (profile_block_flag)
-             {
-               rtx insn = XVECEXP (body, 0, 0);
-               rtx body = PATTERN (insn);
-
-               if ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET
-                    && GET_CODE (SET_SRC (body)) != LABEL_REF)
-                   || (GET_CODE (insn) == JUMP_INSN
-                       && GET_CODE (body) == PARALLEL
-                       && GET_CODE (XVECEXP (body, 0, 0)) == SET
-                       && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF))
-                 new_block = 1;
-             }
            break;
          }
 
@@ -2627,15 +2356,15 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
                && insn != last_ignored_compare)
              {
                if (GET_CODE (SET_SRC (set)) == SUBREG)
-                 SET_SRC (set) = alter_subreg (SET_SRC (set));
+                 SET_SRC (set) = alter_subreg (&SET_SRC (set));
                else if (GET_CODE (SET_SRC (set)) == COMPARE)
                  {
                    if (GET_CODE (XEXP (SET_SRC (set), 0)) == SUBREG)
                      XEXP (SET_SRC (set), 0)
-                       = alter_subreg (XEXP (SET_SRC (set), 0));
+                       = alter_subreg (&XEXP (SET_SRC (set), 0));
                    if (GET_CODE (XEXP (SET_SRC (set), 1)) == SUBREG)
                      XEXP (SET_SRC (set), 1)
-                       = alter_subreg (XEXP (SET_SRC (set), 1));
+                       = alter_subreg (&XEXP (SET_SRC (set), 1));
                  }
                if ((cc_status.value1 != 0
                     && rtx_equal_p (SET_SRC (set), cc_status.value1))
@@ -2643,7 +2372,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)))
                      {
@@ -2656,17 +2385,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
          }
 #endif
 
-       /* Following a conditional branch, we have a new basic block.
-          But if we are inside a sequence, the new block starts after the
-          last insn of the sequence.  */
-       if (profile_block_flag && final_sequence == 0
-           && ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET
-                && GET_CODE (SET_SRC (body)) != LABEL_REF)
-               || (GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == PARALLEL
-                   && GET_CODE (XVECEXP (body, 0, 0)) == SET
-                   && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF)))
-         new_block = 1;
-
 #ifndef STACK_REGS
        /* Don't bother outputting obvious no-ops, even without -O.
           This optimization is fast and doesn't interfere with debugging.
@@ -2906,7 +2624,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
            /* If we didn't split the insn, go away.  */
            if (new == insn && PATTERN (new) == body)
-             fatal_insn ("Could not split insn", insn);
+             fatal_insn ("could not split insn", insn);
 
 #ifdef HAVE_ATTR_length
            /* This instruction should have been split in shorten_branches,
@@ -2971,14 +2689,6 @@ notice_source_line (insn)
 {
   const char *filename = NOTE_SOURCE_FILE (insn);
 
-  /* Remember filename for basic block profiling.
-     Filenames are allocated on the permanent obstack
-     or are passed in ARGV, so we don't have to save
-     the string.  */
-
-  if (profile_block_flag && last_filename != filename)
-    bb_file_label_num = add_bb_string (filename, TRUE);
-
   last_filename = filename;
   last_linenum = NOTE_LINE_NUMBER (insn);
   high_block_linenum = MAX (last_linenum, high_block_linenum);
@@ -2996,22 +2706,27 @@ cleanup_subreg_operands (insn)
   extract_insn_cached (insn);
   for (i = 0; i < recog_data.n_operands; i++)
     {
-      if (GET_CODE (recog_data.operand[i]) == SUBREG)
-       recog_data.operand[i] = alter_subreg (recog_data.operand[i]);
+      /* The following test cannot use recog_data.operand when tesing
+        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)
-       recog_data.operand[i] = walk_alter_subreg (recog_data.operand[i]);
+       recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i]);
     }
 
   for (i = 0; i < recog_data.n_dups; i++)
     {
       if (GET_CODE (*recog_data.dup_loc[i]) == SUBREG)
-       *recog_data.dup_loc[i] = alter_subreg (*recog_data.dup_loc[i]);
+       *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)
-       *recog_data.dup_loc[i] = walk_alter_subreg (*recog_data.dup_loc[i]);
+       *recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i]);
     }
 }
 
@@ -3019,72 +2734,68 @@ cleanup_subreg_operands (insn)
    based on the thing it is a subreg of.  */
 
 rtx
-alter_subreg (x)
-     rtx x;
+alter_subreg (xp)
+     rtx *xp;
 {
+  rtx x = *xp;
   rtx y = SUBREG_REG (x);
 
-  if (GET_CODE (y) == SUBREG)
-    y = alter_subreg (y);
-
-  /* If reload is operating, we may be replacing inside this SUBREG.
-     Check for that and make a new one if so.  */
-  if (reload_in_progress && find_replacement (&SUBREG_REG (x)) != 0)
-    x = copy_rtx (x);
-
-  if (GET_CODE (y) == REG)
-    {
-      int regno = subreg_hard_regno (x, 1);
-
-      PUT_CODE (x, REG);
-      REGNO (x) = regno;
-      ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y);
-      /* This field has a different meaning for REGs and SUBREGs.  Make sure
-        to clear it!  */
-      x->used = 0;
-    }
-  else if (GET_CODE (y) == MEM)
+  /* 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));
+  else
     {
-      HOST_WIDE_INT offset = SUBREG_BYTE (x);
+      rtx new = simplify_subreg (GET_MODE (x), y, GET_MODE (y),
+                                SUBREG_BYTE (x));
 
-      /* Catch these instead of generating incorrect code.  */
-      if ((offset % GET_MODE_SIZE (GET_MODE (x))) != 0)
+      if (new != 0)
+       *xp = new;
+      /* Simplify_subreg can't handle some REG cases, but we have to.  */
+      else if (GET_CODE (y) == REG)
+       {
+         unsigned int regno = subreg_hard_regno (x, 1);
+         PUT_CODE (x, REG);
+         REGNO (x) = regno;
+         ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y);
+         /* This field has a different meaning for REGs and SUBREGs.  Make
+            sure to clear it!  */
+         x->used = 0;
+       }
+      else
        abort ();
-
-      PUT_CODE (x, MEM);
-      MEM_COPY_ATTRIBUTES (x, y);
-      XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
     }
 
-  return x;
+  return *xp;
 }
 
 /* Do alter_subreg on all the SUBREGs contained in X.  */
 
 static rtx
-walk_alter_subreg (x)
-     rtx x;
+walk_alter_subreg (xp)
+     rtx *xp;
 {
+  rtx x = *xp;
   switch (GET_CODE (x))
     {
     case PLUS:
     case MULT:
-      XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));
-      XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1));
+      XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
+      XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1));
       break;
 
     case MEM:
-      XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));
+      XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
       break;
 
     case SUBREG:
-      return alter_subreg (x);
+      return alter_subreg (xp);
 
     default:
       break;
     }
 
-  return x;
+  return *xp;
 }
 \f
 #ifdef HAVE_cc0
@@ -3288,6 +2999,78 @@ output_asm_name ()
     }
 }
 
+/* If OP is a REG or MEM and we can find a MEM_EXPR corresponding to it
+   or its address, return that expr .  Set *PADDRESSP to 1 if the expr
+   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;
+{
+  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)
+    return 0;
+
+  if (MEM_EXPR (op) != 0)
+    return MEM_EXPR (op);
+
+  /* Otherwise we have an address, so indicate it and look at the address.  */
+  *paddressp = 1;
+  op = XEXP (op, 0);
+
+  /* First check if we have a decl for the address, then look at the right side
+     if it is a PLUS.  Otherwise, strip off arithmetic and keep looking.
+     But don't allow the address to itself be indirect.  */
+  if ((expr = get_mem_expr_from_op (op, &inner_addressp)) && ! inner_addressp)
+    return expr;
+  else if (GET_CODE (op) == PLUS
+          && (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')
+    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;
+{
+  int wrote = 0;
+  int i;
+
+  for (i = 0; i < nops; i++)
+    {
+      int addressp;
+      tree expr = get_mem_expr_from_op (operands[oporder[i]], &addressp);
+
+      if (expr)
+       {
+         fprintf (asm_out_file, "%c%s %s",
+                  wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START,
+                  addressp ? "*" : "");
+         print_mem_expr (asm_out_file, expr);
+         wrote = 1;
+       }
+    }
+}
+
 /* Output text from TEMPLATE to the assembler output file,
    obeying %-directions to substitute operands taken from
    the vector OPERANDS.
@@ -3315,6 +3098,7 @@ output_asm_insn (template, operands)
   int dialect = 0;
 #endif
   int oporder[MAX_RECOG_OPERANDS];
+  char opoutput[MAX_RECOG_OPERANDS];
   int ops = 0;
 
   /* An insn may return a null string template
@@ -3322,6 +3106,7 @@ output_asm_insn (template, operands)
   if (*template == 0)
     return;
 
+  memset (opoutput, 0, sizeof opoutput);
   p = template;
   putc ('\t', asm_out_file);
 
@@ -3333,9 +3118,14 @@ output_asm_insn (template, operands)
     switch (c)
       {
       case '\n':
+       if (flag_verbose_asm)
+         output_asm_operand_names (operands, oporder, ops);
        if (flag_print_asm_name)
          output_asm_name ();
 
+       ops = 0;
+       memset (opoutput, 0, sizeof opoutput);
+
        putc (c, asm_out_file);
 #ifdef ASM_OUTPUT_OPCODE
        while ((c = *p) == '\t')
@@ -3385,7 +3175,7 @@ output_asm_insn (template, operands)
                    output_operand_lossage ("unterminated assembly dialect alternative");
                    break;
                  }
-             }   
+             }
            while (*p++ != '}');
            dialect = 0;
          }
@@ -3420,12 +3210,12 @@ output_asm_insn (template, operands)
           Letters `acln' are implemented directly.
           Other letters are passed to `output_operand' so that
           the PRINT_OPERAND macro can define them.  */
-       else if (ISLOWER (*p) || ISUPPER (*p))
+       else if (ISALPHA (*p))
          {
            int letter = *p++;
            c = atoi (p);
 
-           if (! (*p >= '0' && *p <= '9'))
+           if (! ISDIGIT (*p))
              output_operand_lossage ("operand number missing after %-letter");
            else if (this_is_asm_operands
                     && (c < 0 || (unsigned int) c >= insn_noperands))
@@ -3455,13 +3245,15 @@ output_asm_insn (template, operands)
            else
              output_operand (operands[c], letter);
 
-           oporder[ops++] = c;
+           if (!opoutput[c])
+             oporder[ops++] = c;
+           opoutput[c] = 1;
 
-           while ((c = *p) >= '0' && c <= '9')
+           while (ISDIGIT (c = *p))
              p++;
          }
        /* % followed by a digit outputs an operand the default way.  */
-       else if (*p >= '0' && *p <= '9')
+       else if (ISDIGIT (*p))
          {
            c = atoi (p);
            if (this_is_asm_operands
@@ -3470,8 +3262,11 @@ output_asm_insn (template, operands)
            else
              output_operand (operands[c], 0);
 
-           oporder[ops++] = c;
-           while ((c = *p) >= '0' && c <= '9')
+           if (!opoutput[c])
+             oporder[ops++] = c;
+           opoutput[c] = 1;
+
+           while (ISDIGIT (c = *p))
              p++;
          }
        /* % followed by punctuation: output something for that
@@ -3491,26 +3286,7 @@ output_asm_insn (template, operands)
 
   /* Write out the variable names for operands, if we know them.  */
   if (flag_verbose_asm)
-    {
-      int wrote = 0;
-      int i;
-
-      for (i = 0; i < ops; i++)
-       {
-         rtx op = operands[oporder[i]];
-         tree decl = (GET_CODE (op) == REG ? REGNO_DECL (ORIGINAL_REGNO (op))
-                      : GET_CODE (op) == MEM ? MEM_DECL (op)
-                      : 0);
-
-         if (decl && DECL_NAME (decl))
-           {
-             fprintf (asm_out_file, "%s %s", wrote ? "," : ASM_COMMENT_START,
-                      IDENTIFIER_POINTER (DECL_NAME (decl)));
-             wrote = 1;
-           }
-       }
-    }
-
+    output_asm_operand_names (operands, oporder, ops);
   if (flag_print_asm_name)
     output_asm_name ();
 
@@ -3553,7 +3329,7 @@ output_operand (x, code)
      int code ATTRIBUTE_UNUSED;
 {
   if (x && GET_CODE (x) == SUBREG)
-    x = alter_subreg (x);
+    x = alter_subreg (&x);
 
   /* If X is a pseudo-register, abort now rather than writing trash to the
      assembler file.  */
@@ -3572,7 +3348,7 @@ void
 output_address (x)
      rtx x;
 {
-  walk_alter_subreg (x);
+  walk_alter_subreg (&x);
   PRINT_OPERAND_ADDRESS (asm_out_file, x);
 }
 \f
@@ -3591,10 +3367,7 @@ output_addr_const (file, x)
   switch (GET_CODE (x))
     {
     case PC:
-      if (flag_pic)
-       putc ('.', file);
-      else
-       abort ();
+      putc ('.', file);
       break;
 
     case SYMBOL_REF:
@@ -3610,7 +3383,11 @@ output_addr_const (file, x)
       /* Fall through.  */
     case CODE_LABEL:
       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
+#ifdef ASM_OUTPUT_LABEL_REF
+      ASM_OUTPUT_LABEL_REF (file, buf);
+#else
       assemble_name (file, buf);
+#endif
       break;
 
     case CONST_INT:
@@ -3669,16 +3446,16 @@ 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:
@@ -3753,7 +3530,7 @@ asm_fprintf VPARAMS ((FILE *file, const char *p, ...))
       case '%':
        c = *p++;
        q = &buf[1];
-       while ((c >= '0' && c <= '9') || c == '.')
+       while (ISDIGIT (c) || c == '.')
          {
            *q++ = c;
            c = *p++;
@@ -4043,7 +3820,7 @@ leaf_function_p ()
   rtx insn;
   rtx link;
 
-  if (profile_flag || profile_block_flag || profile_arc_flag)
+  if (current_function_profile || profile_arc_flag)
     return 0;
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))