[multiple changes]
authorZack Weinberg <zack@gcc.gnu.org>
Sat, 20 Jan 2001 09:12:08 +0000 (09:12 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Sat, 20 Jan 2001 09:12:08 +0000 (09:12 +0000)
2001-01-20  Jakub Jelinek  <jakub@redhat.com>

* function.c (fixup_var_refs): Move CALL_PLACEHOLDER handling...
(fixup_var_refs_insns): ...here.

* gcc.c-torture/compile/20010118-1.c: New test.

2001-01-20  Zack Weinberg  <zack@wolery.stanford.edu>

* function.c (fixup_var_refs_insns): Break up into
fixup_var_refs_insn [body of loop], fixup_var_refs_insns
[loop over entire insn list], and fixup_var_refs_insns_with_hash
[loop over hash table entries].
(fixup_var_refs): Adjust calls to fixup_var_refs_insns and/or
fixup_var_refs_insns_with_hash, to match above changes.

From-SVN: r39151

gcc/ChangeLog
gcc/function.c
gcc/testsuite/gcc.c-torture/compile/20010118-1.c [new file with mode: 0644]

index 79444c1..46627c8 100644 (file)
@@ -1,3 +1,19 @@
+2001-01-20  Jakub Jelinek  <jakub@redhat.com>
+
+       * function.c (fixup_var_refs): Move CALL_PLACEHOLDER handling...
+       (fixup_var_refs_insns): ...here.
+
+       * gcc.c-torture/compile/20010118-1.c: New test.
+
+2001-01-20  Zack Weinberg  <zack@wolery.stanford.edu>
+
+       * function.c (fixup_var_refs_insns): Break up into
+       fixup_var_refs_insn [body of loop], fixup_var_refs_insns
+       [loop over entire insn list], and fixup_var_refs_insns_with_hash
+       [loop over hash table entries].
+       (fixup_var_refs): Adjust calls to fixup_var_refs_insns and/or
+       fixup_var_refs_insns_with_hash, to match above changes.
+
 2001-01-19  John David Anglin  <dave@hiauly1.hia.nrc.ca>
 
        * Makefile.in (ORDINARY_FLAGS_TO_PASS): Add MAKEOVERRIDES variable.
@@ -12,7 +28,7 @@
 
 2001-01-19  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * cppinternals.texi: Update.
+       * cppinternals.texi: Update.
 
 2001-01-19  Richard Earnshaw  <rearnsha@arm.com>
 
@@ -71,8 +87,8 @@ Thu Jan 18 06:43:04 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
 2001-01-18  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * cpplib.c (_cpp_handle_directive): Use buffer->was_skipping,
-        not pfile->skipping (== 0).
+       * cpplib.c (_cpp_handle_directive): Use buffer->was_skipping,
+       not pfile->skipping (== 0).
 
 2001-01-17  Nick Clifton  <nickc@redhat.com>
 
@@ -90,7 +106,7 @@ Thu Jan 18 06:43:04 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
 2001-01-17  Aldy Hernandez  <aldyh@redhat.com>
 
-        * invoke.texi (-fno-guess-branch-probability): New option.
+       * invoke.texi (-fno-guess-branch-probability): New option.
 
 Wed Jan 17 13:26:34 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
@@ -152,7 +168,7 @@ Tue Jan 16 17:20:43 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
        (movqi_internal, movhi_internal, movsi_internal, movdi_internal,
        movsf_internal, movdf_internal, movtf_internal, cmovdi_internal,
        cmovsi_internal): Delete ! TARGET_A_STEP check.
-       
+
 2001-01-16  Gerald Pfeifer  <pfeifer@dbai.tuwien.ac.at>
 
        * gcc.texi (Bug Lists): Do not mention newsgroups nor the
@@ -165,7 +181,7 @@ Tue Jan 16 17:20:43 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
 2001-01-16  Alan Modra <alan@linuxcare.com.au>
 
-        * cppmain.c (general_init): Don't use ANSI prototype.
+       * cppmain.c (general_init): Don't use ANSI prototype.
 
 2001-01-16  Tom Tromey  <tromey@redhat.com>
 
@@ -268,7 +284,7 @@ Tue Jan 16 17:20:43 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
        (emit_multi_reg_push): Don't record dwarf information for the pc.
        * arm.md (eh_epilogue): The function type may have changed, so it
        needs to be recalculated.
-       * arm/netbsd.h (DWARF2_UNWIND_INFO): Delete.  Can now use dwarf2 
+       * arm/netbsd.h (DWARF2_UNWIND_INFO): Delete.  Can now use dwarf2
        unwind tables on arm/netbsd.
 
 2001-01-15  Richard Earnshaw  <rearnsha@arm.com>
@@ -288,7 +304,7 @@ Tue Jan 16 17:20:43 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
 2001-01-15  Andreas Jaeger  <aj@suse.de>
 
-       * config/i386/i386.c (ix86_init_builtins): Make i size_t to remove 
+       * config/i386/i386.c (ix86_init_builtins): Make i size_t to remove
        warnings.
        (ix86_expand_builtin): Likewise.
 
@@ -301,8 +317,8 @@ Tue Jan 16 17:20:43 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
 2001-01-14  Ralf Baechle <ralf@gnu.org>
 
-        * config/mips/linux.h (SUBTARGET_CPP_SPEC): Default ABI is 32; change
-        SUBTARGET_CPP_SPEC apropriatly.
+       * config/mips/linux.h (SUBTARGET_CPP_SPEC): Default ABI is 32; change
+       SUBTARGET_CPP_SPEC apropriatly.
 
 2001-01-12  Mark Mitchell  <mark@codesourcery.com>
 
@@ -322,12 +338,12 @@ Sun Jan 14 22:31:30 2001  J"orn Rennecke <amylaar@redhat.com>
 
 2001-01-14  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * c-parse.in (finish_parse): Add comment about cpp_destroy.
-        * cp/lex.c (finish_parse): Similarly.
-        * cppinit.c (cpp_cleanup): Rename cpp_destroy for clarity.
-        Return the number of errors encountered.
-        * cpplib.h (cpp_cleanup): Rename cpp_destroy, return int.
-        * cppmain.c (main): Don't call cpp_destroy.
+       * c-parse.in (finish_parse): Add comment about cpp_destroy.
+       * cp/lex.c (finish_parse): Similarly.
+       * cppinit.c (cpp_cleanup): Rename cpp_destroy for clarity.
+       Return the number of errors encountered.
+       * cpplib.h (cpp_cleanup): Rename cpp_destroy, return int.
+       * cppmain.c (main): Don't call cpp_destroy.
 
 2001-01-14  Joseph S. Myers  <jsm28@cam.ac.uk>
 
@@ -351,12 +367,12 @@ Sun Jan 14 22:31:30 2001  J"orn Rennecke <amylaar@redhat.com>
 
 2001-01-14  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * cppmain.c (do_preprocessing): New function; most of the old
-        main.
-        (main): Call it to do most of the work.
-        (cb): Move from global scope to set_callbacks ().
-        (setup_callbacks): Get the callback pointer.
-        (general_init, printer_init): Clean up code and comments.
+       * cppmain.c (do_preprocessing): New function; most of the old
+       main.
+       (main): Call it to do most of the work.
+       (cb): Move from global scope to set_callbacks ().
+       (setup_callbacks): Get the callback pointer.
+       (general_init, printer_init): Clean up code and comments.
 
 2001-01-14  Richard Earnshaw  <rearnsha@arm.com>
 
@@ -491,11 +507,11 @@ Sun Jan 14 00:23:15 2001  Denis Chertykov  <denisc@overta.ru>
 
 2001-01-13  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * cppfiles.c (_cpp_fake_include): New function.
-        * cpphash.h (_cpp_fake_include): New.
-        * cpplib.c (do_line): Call _cpp_fake_include when entering
-        header files in preprocessed input.
-        * cppmain.c (cb_pragma_implementation): Remove handling.
+       * cppfiles.c (_cpp_fake_include): New function.
+       * cpphash.h (_cpp_fake_include): New.
+       * cpplib.c (do_line): Call _cpp_fake_include when entering
+       header files in preprocessed input.
+       * cppmain.c (cb_pragma_implementation): Remove handling.
        (setup_callbacks): Don't register pragmas.
 
 2001-01-13  Neil Booth  <neil@daikokuya.demon.co.uk>
@@ -510,35 +526,35 @@ Sun Jan 14 00:23:15 2001  Denis Chertykov  <denisc@overta.ru>
 
 2001-01-13  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * cpplib.h (cpp_pool, mi_state, mi_ind, struct cpp_macro,
-        struct cpp_chunk, struct htab, struct toklist,
-        struct cpp_context, CPP_STACK_MAX, struct lexer_state,
-        struct spec_nodes, struct cpp_reader, CPP_OPTION, CPP_BUFFER,
-        CPP_BUF_LINE, CPP_BUF_COL, CPP_BUF_COLUMN, U, ustrcmp, ustrncmp,
-        ustrlen, uxstrdup, ustrchr, ufputs): Move to cpphash.h.
-        (struct macro_args): Delete.
-        * cpphash.h: See above.
+       * cpplib.h (cpp_pool, mi_state, mi_ind, struct cpp_macro,
+       struct cpp_chunk, struct htab, struct toklist,
+       struct cpp_context, CPP_STACK_MAX, struct lexer_state,
+       struct spec_nodes, struct cpp_reader, CPP_OPTION, CPP_BUFFER,
+       CPP_BUF_LINE, CPP_BUF_COL, CPP_BUF_COLUMN, U, ustrcmp, ustrncmp,
+       ustrlen, uxstrdup, ustrchr, ufputs): Move to cpphash.h.
+       (struct macro_args): Delete.
+       * cpphash.h: See above.
 
 2001-01-13  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * cppmain.c (struct printer): Remove no_line_dirs.
-        (options, cb): New.
-        (main, setup_callbacks, scan_buffer, printer_init, cb_define)
-        : Use options rather than CPP_OPTION.
-        (setup_callbacks): Use cb rather than pfile->cb.
-        (main): No need to check for a buffer.  Use cpp_errors.
-        (printer_init): Don't set no_line_dirs.
-        (maybe_print_line): Use options not no_line_dirs.
-        (cb_file_change): Don't call print_line if -P.
+       * cppmain.c (struct printer): Remove no_line_dirs.
+       (options, cb): New.
+       (main, setup_callbacks, scan_buffer, printer_init, cb_define)
+       : Use options rather than CPP_OPTION.
+       (setup_callbacks): Use cb rather than pfile->cb.
+       (main): No need to check for a buffer.  Use cpp_errors.
+       (printer_init): Don't set no_line_dirs.
+       (maybe_print_line): Use options not no_line_dirs.
+       (cb_file_change): Don't call print_line if -P.
 
 2001-01-13  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * c-lex.c (init_c_lex): Use cpp_get_callbacks to set
-        callbacks.
-        * c-parse.in (finish_parse): Use cpp_errors.
-        (__yylex): Use return value of cpp_pop_buffer.
-        * cp/lex.c (finish_parse): Use cpp_errors.
-        * cp/spew.c (read_token): Use return value of cpp_pop_buffer.
+       * c-lex.c (init_c_lex): Use cpp_get_callbacks to set
+       callbacks.
+       * c-parse.in (finish_parse): Use cpp_errors.
+       (__yylex): Use return value of cpp_pop_buffer.
+       * cp/lex.c (finish_parse): Use cpp_errors.
+       * cp/spew.c (read_token): Use return value of cpp_pop_buffer.
 
 Sat Jan 13 16:57:40 2001  Denis Chertykov  <denisc@overta.ru>
 
@@ -592,24 +608,24 @@ Sat Jan 13 09:53:32 MET 2001  Jan Hubicka  <jh@suse.cz>
 
 2001-01-13  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * fix-header.c (read_scan_file): Use cpp_get_callbacks and
-        cpp_get_options rather than dereferencing pfile and using
-        CPP_OPTION.
-        * scan-decls.c (scan_decls): Use return value of
-        cpp_pop_buffer rather than CPP_BUFFER.
+       * fix-header.c (read_scan_file): Use cpp_get_callbacks and
+       cpp_get_options rather than dereferencing pfile and using
+       CPP_OPTION.
+       * scan-decls.c (scan_decls): Use return value of
+       cpp_pop_buffer rather than CPP_BUFFER.
 
 2001-01-13  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * cppinit.c (cpp_handle_option): help_only is now part of the
-        cpp_options structure.
-        * cpplib.c (cpp_errors, cpp_get_options, cpp_get_callbacks,
-        cpp_set_callbacks): New functions.
-        * cpplib.h (cpp_callbacks): Break out as a named structure.
-        (cpp_options): Move help_only here from cpp_reader.
-        (CPP_FATAL_ERRORS): Update to use cpp_errors.
-        (cpp_errors, cpp_get_options, cpp_get_callbacks,
-        cpp_set_callbacks): New prototypes.
-        * cppmain.c (main): Update for help_only.
+       * cppinit.c (cpp_handle_option): help_only is now part of the
+       cpp_options structure.
+       * cpplib.c (cpp_errors, cpp_get_options, cpp_get_callbacks,
+       cpp_set_callbacks): New functions.
+       * cpplib.h (cpp_callbacks): Break out as a named structure.
+       (cpp_options): Move help_only here from cpp_reader.
+       (CPP_FATAL_ERRORS): Update to use cpp_errors.
+       (cpp_errors, cpp_get_options, cpp_get_callbacks,
+       cpp_set_callbacks): New prototypes.
+       * cppmain.c (main): Update for help_only.
 
 2001-01-13  Joseph S. Myers  <jsm28@cam.ac.uk>
 
index 22a5a74..8e7eeae 100644 (file)
@@ -253,8 +253,13 @@ static void fixup_var_refs PARAMS ((rtx, enum machine_mode, int,
                                         struct hash_table *));
 static struct fixup_replacement
   *find_fixup_replacement      PARAMS ((struct fixup_replacement **, rtx));
-static void fixup_var_refs_insns PARAMS ((rtx, enum machine_mode, int,
-                                         rtx, int, struct hash_table *));
+static void fixup_var_refs_insns PARAMS ((rtx, rtx, enum machine_mode,
+                                         int, int));
+static void fixup_var_refs_insns_with_hash
+                               PARAMS ((struct hash_table *, rtx,
+                                        enum machine_mode, int));
+static void fixup_var_refs_insn PARAMS ((rtx, rtx, enum machine_mode,
+                                        int, int));
 static void fixup_var_refs_1   PARAMS ((rtx, enum machine_mode, rtx *, rtx,
                                         struct fixup_replacement **));
 static rtx fixup_memory_subreg PARAMS ((rtx, rtx, int));
@@ -1542,21 +1547,25 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht)
   rtx first_insn = get_insns ();
   struct sequence_stack *stack = seq_stack;
   tree rtl_exps = rtl_expr_chain;
-  rtx insn;
 
-  /* Must scan all insns for stack-refs that exceed the limit.  */
-  fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn,
-                       stack == 0, ht);
   /* If there's a hash table, it must record all uses of VAR.  */
   if (ht)
-    return;
+    {
+      if (stack != 0)
+       abort ();
+      fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp);
+      return;
+    }
+
+  fixup_var_refs_insns (first_insn, var, promoted_mode, unsignedp,
+                       stack == 0);
 
   /* Scan all pending sequences too.  */
   for (; stack; stack = stack->next)
     {
       push_to_full_sequence (stack->first, stack->last);
-      fixup_var_refs_insns (var, promoted_mode, unsignedp,
-                           stack->first, stack->next != 0, 0);
+      fixup_var_refs_insns (stack->first, var, promoted_mode, unsignedp,
+                           stack->next != 0);
       /* Update remembered end of sequence
         in case we added an insn at the end.  */
       stack->last = get_last_insn ();
@@ -1570,40 +1579,15 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht)
       if (seq != const0_rtx && seq != 0)
        {
          push_to_sequence (seq);
-         fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0, 0);
+         fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0);
          end_sequence ();
        }
     }
 
   /* Scan the catch clauses for exception handling too.  */
   push_to_full_sequence (catch_clauses, catch_clauses_last);
-  fixup_var_refs_insns (var, promoted_mode, unsignedp, catch_clauses, 0, 0);
+  fixup_var_refs_insns (catch_clauses, var, promoted_mode, unsignedp, 0);
   end_full_sequence (&catch_clauses, &catch_clauses_last);
-
-  /* Scan sequences saved in CALL_PLACEHOLDERS too.  */
-  for (insn = first_insn; insn; insn = NEXT_INSN (insn))
-    {
-      if (GET_CODE (insn) == CALL_INSN
-         && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
-       {
-         int i;
-
-         /* Look at the Normal call, sibling call and tail recursion
-            sequences attached to the CALL_PLACEHOLDER.  */
-         for (i = 0; i < 3; i++)
-           {
-             rtx seq = XEXP (PATTERN (insn), i);
-             if (seq)
-               {
-                 push_to_sequence (seq);
-                 fixup_var_refs_insns (var, promoted_mode, unsignedp,
-                                       seq, 0, 0);
-                 XEXP (PATTERN (insn), i) = get_insns ();
-                 end_sequence ();
-               }
-           }
-       }
-    }
 }
 \f
 /* REPLACEMENTS is a pointer to a list of the struct fixup_replacement and X is
@@ -1638,218 +1622,265 @@ find_fixup_replacement (replacements, x)
    main chain of insns for the current function.  */
 
 static void
-fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel, ht)
+fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel)
+     rtx insn;
      rtx var;
      enum machine_mode promoted_mode;
      int unsignedp;
-     rtx insn;
      int toplevel;
+{
+  while (insn)
+    {
+      /* fixup_var_refs_insn might modify insn, so save its next
+         pointer now.  */
+      rtx next = NEXT_INSN (insn);
+
+      /* CALL_PLACEHOLDERs are special; we have to switch into each of
+        the three sequences they (potentially) contain, and process
+        them recursively.  The CALL_INSN itself is not interesting.  */
+
+      if (GET_CODE (insn) == CALL_INSN
+         && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
+       {
+         int i;
+
+         /* Look at the Normal call, sibling call and tail recursion
+            sequences attached to the CALL_PLACEHOLDER.  */
+         for (i = 0; i < 3; i++)
+           {
+             rtx seq = XEXP (PATTERN (insn), i);
+             if (seq)
+               {
+                 push_to_sequence (seq);
+                 fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0);
+                 XEXP (PATTERN (insn), i) = get_insns ();
+                 end_sequence ();
+               }
+           }
+       }
+
+      else if (INSN_P (insn))
+       fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel);
+
+      insn = next;
+    }
+}
+
+/* Look up the insns which reference VAR in HT and fix them up.  Other
+   arguments are the same as fixup_var_refs_insns.
+
+   N.B. No need for special processing of CALL_PLACEHOLDERs here,
+   because the hash table will point straight to the interesting insn
+   (inside the CALL_PLACEHOLDER).  */
+static void
+fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp)
      struct hash_table *ht;
+     rtx var;
+     enum machine_mode promoted_mode;
+     int unsignedp;
 {
-  rtx call_dest = 0;
-  rtx insn_list = NULL_RTX;
+  struct insns_for_mem_entry *ime = (struct insns_for_mem_entry *)
+    hash_lookup (ht, var, /*create=*/0, /*copy=*/0);
+  rtx insn_list = ime->insns;
 
-  /* If we already know which INSNs reference VAR there's no need
-     to walk the entire instruction chain.  */
-  if (ht)
+  while (insn_list)
     {
-      insn_list = ((struct insns_for_mem_entry *)
-                  hash_lookup (ht, var, /*create=*/0, /*copy=*/0))->insns;
-      insn = insn_list ? XEXP (insn_list, 0) : NULL_RTX;
+      rtx insn = XEXP (insn_list, 0);
+       
+      if (INSN_P (insn))
+       fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, 0);
+
       insn_list = XEXP (insn_list, 1);
     }
+}
 
-  while (insn)
+
+/* Per-insn processing by fixup_var_refs_insns(_with_hash).  INSN is
+   the insn under examination, VAR is the variable to fix up
+   references to, PROMOTED_MODE and UNSIGNEDP describe VAR, and
+   TOPLEVEL is nonzero if this is the main insn chain for this
+   function.  */
+static void
+fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel)
+     rtx insn;
+     rtx var;
+     enum machine_mode promoted_mode;
+     int unsignedp;
+     int toplevel;
+{
+  rtx call_dest = 0;
+  rtx set, prev, prev_set;
+  rtx note;
+
+  /* Remember the notes in case we delete the insn.  */
+  note = REG_NOTES (insn);
+
+  /* If this is a CLOBBER of VAR, delete it.
+
+     If it has a REG_LIBCALL note, delete the REG_LIBCALL
+     and REG_RETVAL notes too.  */
+  if (GET_CODE (PATTERN (insn)) == CLOBBER
+      && (XEXP (PATTERN (insn), 0) == var
+         || (GET_CODE (XEXP (PATTERN (insn), 0)) == CONCAT
+             && (XEXP (XEXP (PATTERN (insn), 0), 0) == var
+                 || XEXP (XEXP (PATTERN (insn), 0), 1) == var))))
     {
-      rtx next = NEXT_INSN (insn);
-      rtx set, prev, prev_set;
-      rtx note;
+      if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0)
+       /* The REG_LIBCALL note will go away since we are going to
+          turn INSN into a NOTE, so just delete the
+          corresponding REG_RETVAL note.  */
+       remove_note (XEXP (note, 0),
+                    find_reg_note (XEXP (note, 0), REG_RETVAL,
+                                   NULL_RTX));
+
+      /* In unoptimized compilation, we shouldn't call delete_insn
+        except in jump.c doing warnings.  */
+      PUT_CODE (insn, NOTE);
+      NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+      NOTE_SOURCE_FILE (insn) = 0;
+    }
 
-      if (INSN_P (insn))
+  /* The insn to load VAR from a home in the arglist
+     is now a no-op.  When we see it, just delete it.
+     Similarly if this is storing VAR from a register from which
+     it was loaded in the previous insn.  This will occur
+     when an ADDRESSOF was made for an arglist slot.  */
+  else if (toplevel
+          && (set = single_set (insn)) != 0
+          && SET_DEST (set) == var
+          /* If this represents the result of an insn group,
+             don't delete the insn.  */
+          && find_reg_note (insn, REG_RETVAL, NULL_RTX) == 0
+          && (rtx_equal_p (SET_SRC (set), var)
+              || (GET_CODE (SET_SRC (set)) == REG
+                  && (prev = prev_nonnote_insn (insn)) != 0
+                  && (prev_set = single_set (prev)) != 0
+                  && SET_DEST (prev_set) == SET_SRC (set)
+                  && rtx_equal_p (SET_SRC (prev_set), var))))
+    {
+      /* In unoptimized compilation, we shouldn't call delete_insn
+        except in jump.c doing warnings.  */
+      PUT_CODE (insn, NOTE);
+      NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+      NOTE_SOURCE_FILE (insn) = 0;
+    }
+  else
+    {
+      struct fixup_replacement *replacements = 0;
+      rtx next_insn = NEXT_INSN (insn);
+
+      if (SMALL_REGISTER_CLASSES)
        {
-         /* Remember the notes in case we delete the insn.  */
-         note = REG_NOTES (insn);
-
-         /* If this is a CLOBBER of VAR, delete it.
-
-            If it has a REG_LIBCALL note, delete the REG_LIBCALL
-            and REG_RETVAL notes too.  */
-         if (GET_CODE (PATTERN (insn)) == CLOBBER
-             && (XEXP (PATTERN (insn), 0) == var
-                 || (GET_CODE (XEXP (PATTERN (insn), 0)) == CONCAT
-                     && (XEXP (XEXP (PATTERN (insn), 0), 0) == var
-                         || XEXP (XEXP (PATTERN (insn), 0), 1) == var))))
+         /* If the insn that copies the results of a CALL_INSN
+            into a pseudo now references VAR, we have to use an
+            intermediate pseudo since we want the life of the
+            return value register to be only a single insn.
+
+            If we don't use an intermediate pseudo, such things as
+            address computations to make the address of VAR valid
+            if it is not can be placed between the CALL_INSN and INSN.
+
+            To make sure this doesn't happen, we record the destination
+            of the CALL_INSN and see if the next insn uses both that
+            and VAR.  */
+
+         if (call_dest != 0 && GET_CODE (insn) == INSN
+             && reg_mentioned_p (var, PATTERN (insn))
+             && reg_mentioned_p (call_dest, PATTERN (insn)))
            {
-             if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0)
-               /* The REG_LIBCALL note will go away since we are going to
-                  turn INSN into a NOTE, so just delete the
-                  corresponding REG_RETVAL note.  */
-               remove_note (XEXP (note, 0),
-                            find_reg_note (XEXP (note, 0), REG_RETVAL,
-                                           NULL_RTX));
-
-             /* In unoptimized compilation, we shouldn't call delete_insn
-                except in jump.c doing warnings.  */
-             PUT_CODE (insn, NOTE);
-             NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (insn) = 0;
-           }
+             rtx temp = gen_reg_rtx (GET_MODE (call_dest));
 
-         /* The insn to load VAR from a home in the arglist
-            is now a no-op.  When we see it, just delete it.
-            Similarly if this is storing VAR from a register from which
-            it was loaded in the previous insn.  This will occur
-            when an ADDRESSOF was made for an arglist slot.  */
-         else if (toplevel
-                  && (set = single_set (insn)) != 0
-                  && SET_DEST (set) == var
-                  /* If this represents the result of an insn group,
-                     don't delete the insn.  */
-                  && find_reg_note (insn, REG_RETVAL, NULL_RTX) == 0
-                  && (rtx_equal_p (SET_SRC (set), var)
-                      || (GET_CODE (SET_SRC (set)) == REG
-                          && (prev = prev_nonnote_insn (insn)) != 0
-                          && (prev_set = single_set (prev)) != 0
-                          && SET_DEST (prev_set) == SET_SRC (set)
-                          && rtx_equal_p (SET_SRC (prev_set), var))))
-           {
-             /* In unoptimized compilation, we shouldn't call delete_insn
-                except in jump.c doing warnings.  */
-             PUT_CODE (insn, NOTE);
-             NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (insn) = 0;
-             if (insn == last_parm_insn)
-               last_parm_insn = PREV_INSN (next);
+             emit_insn_before (gen_move_insn (temp, call_dest), insn);
+
+             PATTERN (insn) = replace_rtx (PATTERN (insn),
+                                           call_dest, temp);
            }
+
+         if (GET_CODE (insn) == CALL_INSN
+             && GET_CODE (PATTERN (insn)) == SET)
+           call_dest = SET_DEST (PATTERN (insn));
+         else if (GET_CODE (insn) == CALL_INSN
+                  && GET_CODE (PATTERN (insn)) == PARALLEL
+                  && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
+           call_dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
          else
-           {
-             struct fixup_replacement *replacements = 0;
-             rtx next_insn = NEXT_INSN (insn);
+           call_dest = 0;
+       }
 
-             if (SMALL_REGISTER_CLASSES)
-               {
-                 /* If the insn that copies the results of a CALL_INSN
-                    into a pseudo now references VAR, we have to use an
-                    intermediate pseudo since we want the life of the
-                    return value register to be only a single insn.
-
-                    If we don't use an intermediate pseudo, such things as
-                    address computations to make the address of VAR valid
-                    if it is not can be placed between the CALL_INSN and INSN.
-
-                    To make sure this doesn't happen, we record the destination
-                    of the CALL_INSN and see if the next insn uses both that
-                    and VAR.  */
-
-                 if (call_dest != 0 && GET_CODE (insn) == INSN
-                     && reg_mentioned_p (var, PATTERN (insn))
-                     && reg_mentioned_p (call_dest, PATTERN (insn)))
-                   {
-                     rtx temp = gen_reg_rtx (GET_MODE (call_dest));
+      /* See if we have to do anything to INSN now that VAR is in
+        memory.  If it needs to be loaded into a pseudo, use a single
+        pseudo for the entire insn in case there is a MATCH_DUP
+        between two operands.  We pass a pointer to the head of
+        a list of struct fixup_replacements.  If fixup_var_refs_1
+        needs to allocate pseudos or replacement MEMs (for SUBREGs),
+        it will record them in this list.
 
-                     emit_insn_before (gen_move_insn (temp, call_dest), insn);
+        If it allocated a pseudo for any replacement, we copy into
+        it here.  */
 
-                     PATTERN (insn) = replace_rtx (PATTERN (insn),
-                                                   call_dest, temp);
-                   }
+      fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
+                       &replacements);
 
-                 if (GET_CODE (insn) == CALL_INSN
-                     && GET_CODE (PATTERN (insn)) == SET)
-                   call_dest = SET_DEST (PATTERN (insn));
-                 else if (GET_CODE (insn) == CALL_INSN
-                          && GET_CODE (PATTERN (insn)) == PARALLEL
-                          && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
-                   call_dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
-                 else
-                   call_dest = 0;
-               }
+      /* If this is last_parm_insn, and any instructions were output
+        after it to fix it up, then we must set last_parm_insn to
+        the last such instruction emitted.  */
+      if (insn == last_parm_insn)
+       last_parm_insn = PREV_INSN (next_insn);
 
-             /* See if we have to do anything to INSN now that VAR is in
-                memory.  If it needs to be loaded into a pseudo, use a single
-                pseudo for the entire insn in case there is a MATCH_DUP
-                between two operands.  We pass a pointer to the head of
-                a list of struct fixup_replacements.  If fixup_var_refs_1
-                needs to allocate pseudos or replacement MEMs (for SUBREGs),
-                it will record them in this list.
-
-                If it allocated a pseudo for any replacement, we copy into
-                it here.  */
+      while (replacements)
+       {
+         struct fixup_replacement *next;
 
-             fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
-                               &replacements);
+         if (GET_CODE (replacements->new) == REG)
+           {
+             rtx insert_before;
+             rtx seq;
 
-             /* If this is last_parm_insn, and any instructions were output
-                after it to fix it up, then we must set last_parm_insn to
-                the last such instruction emitted.  */
-             if (insn == last_parm_insn)
-               last_parm_insn = PREV_INSN (next_insn);
+             /* OLD might be a (subreg (mem)).  */
+             if (GET_CODE (replacements->old) == SUBREG)
+               replacements->old
+                 = fixup_memory_subreg (replacements->old, insn, 0);
+             else
+               replacements->old
+                 = fixup_stack_1 (replacements->old, insn);
 
-             while (replacements)
-               {
-                 struct fixup_replacement *next;
+             insert_before = insn;
 
-                 if (GET_CODE (replacements->new) == REG)
-                   {
-                     rtx insert_before;
-                     rtx seq;
-
-                     /* OLD might be a (subreg (mem)).  */
-                     if (GET_CODE (replacements->old) == SUBREG)
-                       replacements->old
-                         = fixup_memory_subreg (replacements->old, insn, 0);
-                     else
-                       replacements->old
-                         = fixup_stack_1 (replacements->old, insn);
-
-                     insert_before = insn;
-
-                     /* If we are changing the mode, do a conversion.
-                        This might be wasteful, but combine.c will
-                        eliminate much of the waste.  */
-
-                     if (GET_MODE (replacements->new)
-                         != GET_MODE (replacements->old))
-                       {
-                         start_sequence ();
-                         convert_move (replacements->new,
-                                       replacements->old, unsignedp);
-                         seq = gen_sequence ();
-                         end_sequence ();
-                       }
-                     else
-                       seq = gen_move_insn (replacements->new,
-                                            replacements->old);
-
-                     emit_insn_before (seq, insert_before);
-                   }
+             /* If we are changing the mode, do a conversion.
+                This might be wasteful, but combine.c will
+                eliminate much of the waste.  */
 
-                 next = replacements->next;
-                 free (replacements);
-                 replacements = next;
+             if (GET_MODE (replacements->new)
+                 != GET_MODE (replacements->old))
+               {
+                 start_sequence ();
+                 convert_move (replacements->new,
+                               replacements->old, unsignedp);
+                 seq = gen_sequence ();
+                 end_sequence ();
                }
-           }
+             else
+               seq = gen_move_insn (replacements->new,
+                                    replacements->old);
 
-         /* Also fix up any invalid exprs in the REG_NOTES of this insn.
-            But don't touch other insns referred to by reg-notes;
-            we will get them elsewhere.  */
-         while (note)
-           {
-             if (GET_CODE (note) != INSN_LIST)
-               XEXP (note, 0)
-                 = walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
-             note = XEXP (note, 1);
+             emit_insn_before (seq, insert_before);
            }
-       }
 
-      if (!ht)
-       insn = next;
-      else if (insn_list)
-       {
-         insn = XEXP (insn_list, 0);
-         insn_list = XEXP (insn_list, 1);
+         next = replacements->next;
+         free (replacements);
+         replacements = next;
        }
-      else
-       insn = NULL_RTX;
+    }
+
+  /* Also fix up any invalid exprs in the REG_NOTES of this insn.
+     But don't touch other insns referred to by reg-notes;
+     we will get them elsewhere.  */
+  while (note)
+    {
+      if (GET_CODE (note) != INSN_LIST)
+       XEXP (note, 0)
+         = walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
+      note = XEXP (note, 1);
     }
 }
 \f
@@ -1861,7 +1892,7 @@ fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel, ht)
    to modify this insn by replacing a memory reference with a pseudo or by
    making a new MEM to implement a SUBREG, we consult that list to see if
    we have already chosen a replacement. If none has already been allocated,
-   we allocate it and update the list.  fixup_var_refs_insns will copy VAR
+   we allocate it and update the list.  fixup_var_refs_insn will copy VAR
    or the SUBREG, as appropriate, to the pseudo.  */
 
 static void
@@ -4564,7 +4595,7 @@ assign_parms (fndecl)
                && GET_CODE (XEXP (XVECEXP (entry_parm, 0, i), 0)) == REG
                && (GET_MODE (XEXP (XVECEXP (entry_parm, 0, i), 0))
                    == passed_mode)
-               && INTVAL (XEXP (XVECEXP (entry_parm, 0, i), 1)) == 0)
+               && XINT (XEXP (XVECEXP (entry_parm, 0, i), 1), 0) == 0)
              {
                entry_parm = XEXP (XVECEXP (entry_parm, 0, i), 0);
                DECL_INCOMING_RTL (parm) = entry_parm;
diff --git a/gcc/testsuite/gcc.c-torture/compile/20010118-1.c b/gcc/testsuite/gcc.c-torture/compile/20010118-1.c
new file mode 100644 (file)
index 0000000..6d1fc64
--- /dev/null
@@ -0,0 +1,21 @@
+static unsigned int bar(void *h, unsigned int n)
+{
+  static int i;
+  return i++;
+}
+
+static void baz(unsigned int *x)
+{
+  (*x)++;
+}
+
+long
+foo(void *h, unsigned int l)
+{
+  unsigned int n;
+  long m;
+  n = bar(h, 0);
+  n = bar(h, n);
+  m = ({ baz(&n); 21; });
+  return m;
+}