+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.
2001-01-19 Neil Booth <neil@daikokuya.demon.co.uk>
- * cppinternals.texi: Update.
+ * cppinternals.texi: Update.
2001-01-19 Richard Earnshaw <rearnsha@arm.com>
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>
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>
(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
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>
(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>
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.
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>
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>
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>
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>
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>
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>
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));
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 ();
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
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
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
&& 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;