OSDN Git Service

* mips.c (mips_function_value): Only promote_mode for non-libcalls.
[pf3gnuchains/gcc-fork.git] / gcc / final.c
index 9302fea..47dd455 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.
 
@@ -114,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;
 
@@ -206,46 +202,15 @@ 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 void output_asm_name    PARAMS ((void));
-static tree get_decl_from_op   PARAMS ((rtx, int *));
+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
@@ -282,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;
@@ -347,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);
@@ -410,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);
       }
 
@@ -446,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);
-       }
     }
 }
 
@@ -603,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_;
@@ -618,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)]
@@ -860,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
@@ -994,7 +831,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.
@@ -1046,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.  */
 
@@ -1123,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)
@@ -1186,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.  */
@@ -1369,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
     }
 
@@ -1678,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
 
@@ -1690,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 */
 
@@ -1715,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
@@ -1723,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);
@@ -1846,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.
@@ -2044,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;
 }
@@ -2113,6 +1851,7 @@ 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:
@@ -2160,7 +1899,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));
 
@@ -2180,7 +1921,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));
 
@@ -2479,11 +2222,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);
@@ -2590,22 +2328,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;
          }
 
@@ -2651,7 +2373,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)))
                      {
@@ -2664,17 +2386,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.
@@ -2914,7 +2625,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,
@@ -2979,14 +2690,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);
@@ -3004,7 +2707,12 @@ 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)
+      /* 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
@@ -3047,8 +2755,9 @@ alter_subreg (xp)
       /* Simplify_subreg can't handle some REG cases, but we have to.  */
       else if (GET_CODE (y) == REG)
        {
-         REGNO (x) = subreg_hard_regno (x, 1);
+         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!  */
@@ -3087,7 +2796,7 @@ walk_alter_subreg (xp)
       break;
     }
 
-  return x;
+  return *xp;
 }
 \f
 #ifdef HAVE_cc0
@@ -3256,13 +2965,26 @@ 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 VPARAMS ((const char *msgid, ...))
 {
+  char *fmt_string;
+  char *new_message;
+  const char *pfx_str;
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, const char *, 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_CLOSE (ap);
 }
 \f
 /* Output of assembler code from a template, and its subroutines.  */
@@ -3291,16 +3013,16 @@ output_asm_name ()
     }
 }
 
-/* If OP is a REG or MEM and we can find a decl corresponding to it or
-   its address, return that decl.  Set *PADDRESSP to 1 if the decl
+/* 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_decl_from_op (op, paddressp)
+get_mem_expr_from_op (op, paddressp)
      rtx op;
      int *paddressp;
 {
-  tree decl;
+  tree expr;
   int inner_addressp;
 
   *paddressp = 0;
@@ -3310,8 +3032,8 @@ get_decl_from_op (op, paddressp)
   else if (GET_CODE (op) != MEM)
     return 0;
 
-  if (MEM_DECL (op) != 0)
-    return MEM_DECL (op);
+  if (MEM_EXPR (op) != 0)
+    return MEM_EXPR (op);
 
   /* Otherwise we have an address, so indicate it and look at the address.  */
   *paddressp = 1;
@@ -3320,20 +3042,20 @@ get_decl_from_op (op, paddressp)
   /* 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 ((decl = get_decl_from_op (op, &inner_addressp)) && ! inner_addressp)
-    return decl;
+  if ((expr = get_mem_expr_from_op (op, &inner_addressp)) && ! inner_addressp)
+    return expr;
   else if (GET_CODE (op) == PLUS
-          && (decl = get_decl_from_op (XEXP (op, 1), &inner_addressp)))
-    return decl;
+          && (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);
 
-  decl = get_decl_from_op (op, &inner_addressp);
-  return inner_addressp ? 0 : decl;
+  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.  */
@@ -3350,13 +3072,14 @@ output_asm_operand_names (operands, oporder, nops)
   for (i = 0; i < nops; i++)
     {
       int addressp;
-      tree decl = get_decl_from_op (operands[oporder[i]], &addressp);
+      tree expr = get_mem_expr_from_op (operands[oporder[i]], &addressp);
 
-      if (decl && DECL_NAME (decl))
+      if (expr)
        {
-         fprintf (asm_out_file, "%c%s %s%s",
+         fprintf (asm_out_file, "%c%s %s",
                   wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START,
-                  addressp ? "*" : "", IDENTIFIER_POINTER (DECL_NAME (decl)));
+                  addressp ? "*" : "");
+         print_mem_expr (asm_out_file, expr);
          wrote = 1;
        }
     }
@@ -3466,7 +3189,7 @@ output_asm_insn (template, operands)
                    output_operand_lossage ("unterminated assembly dialect alternative");
                    break;
                  }
-             }   
+             }
            while (*p++ != '}');
            dialect = 0;
          }
@@ -3507,7 +3230,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");
@@ -3599,7 +3322,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);
 }
@@ -3658,10 +3381,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:
@@ -3740,20 +3460,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;
 
@@ -4050,7 +3771,6 @@ split_double (value, first, second)
     }
   else
     {
-#ifdef REAL_ARITHMETIC
       REAL_VALUE_TYPE r;
       long l[2];
       REAL_VALUE_FROM_CONST_DOUBLE (r, value);
@@ -4079,30 +3799,6 @@ 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
@@ -4114,7 +3810,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))