[multiple changes]
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
This commit is contained in:
parent
1b7f6755f9
commit
a42a5f59d0
146
gcc/ChangeLog
146
gcc/ChangeLog
|
@ -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>
|
||||
|
||||
|
|
487
gcc/function.c
487
gcc/function.c
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
struct hash_table *ht;
|
||||
{
|
||||
rtx call_dest = 0;
|
||||
rtx insn_list = NULL_RTX;
|
||||
|
||||
/* If we already know which INSNs reference VAR there's no need
|
||||
to walk the entire instruction chain. */
|
||||
if (ht)
|
||||
{
|
||||
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;
|
||||
insn_list = XEXP (insn_list, 1);
|
||||
}
|
||||
|
||||
while (insn)
|
||||
{
|
||||
/* fixup_var_refs_insn might modify insn, so save its next
|
||||
pointer now. */
|
||||
rtx next = NEXT_INSN (insn);
|
||||
rtx set, prev, prev_set;
|
||||
rtx note;
|
||||
|
||||
/* 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;
|
||||
{
|
||||
struct insns_for_mem_entry *ime = (struct insns_for_mem_entry *)
|
||||
hash_lookup (ht, var, /*create=*/0, /*copy=*/0);
|
||||
rtx insn_list = ime->insns;
|
||||
|
||||
while (insn_list)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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))))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 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 this is a CLOBBER of VAR, delete it.
|
||||
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.
|
||||
|
||||
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))))
|
||||
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));
|
||||
rtx temp = gen_reg_rtx (GET_MODE (call_dest));
|
||||
|
||||
/* 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;
|
||||
emit_insn_before (gen_move_insn (temp, call_dest), insn);
|
||||
|
||||
PATTERN (insn) = replace_rtx (PATTERN (insn),
|
||||
call_dest, temp);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
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);
|
||||
|
||||
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));
|
||||
|
||||
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
|
||||
call_dest = 0;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
|
||||
&replacements);
|
||||
|
||||
/* 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);
|
||||
|
||||
while (replacements)
|
||||
{
|
||||
struct fixup_replacement *next;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
next = replacements->next;
|
||||
free (replacements);
|
||||
replacements = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
call_dest = 0;
|
||||
}
|
||||
|
||||
if (!ht)
|
||||
insn = next;
|
||||
else if (insn_list)
|
||||
/* 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. */
|
||||
|
||||
fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
|
||||
&replacements);
|
||||
|
||||
/* 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);
|
||||
|
||||
while (replacements)
|
||||
{
|
||||
insn = XEXP (insn_list, 0);
|
||||
insn_list = XEXP (insn_list, 1);
|
||||
struct fixup_replacement *next;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue