1991-09-30 02:34:16 +01:00
|
|
|
/* Communication between reload.c and reload1.c.
|
1998-05-06 01:18:02 +02:00
|
|
|
Copyright (C) 1987, 91-95, 97, 1998 Free Software Foundation, Inc.
|
1991-09-30 02:34:16 +01:00
|
|
|
|
|
|
|
This file is part of GNU CC.
|
|
|
|
|
|
|
|
GNU CC is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
GNU CC is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with GNU CC; see the file COPYING. If not, write to
|
1995-06-15 14:04:37 +02:00
|
|
|
the Free Software Foundation, 59 Temple Place - Suite 330,
|
|
|
|
Boston, MA 02111-1307, USA. */
|
1991-09-30 02:34:16 +01:00
|
|
|
|
|
|
|
|
1991-11-15 01:36:37 +01:00
|
|
|
/* If secondary reloads are the same for inputs and outputs, define those
|
|
|
|
macros here. */
|
|
|
|
|
|
|
|
#ifdef SECONDARY_RELOAD_CLASS
|
|
|
|
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
|
|
|
|
SECONDARY_RELOAD_CLASS (CLASS, MODE, X)
|
|
|
|
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
|
|
|
|
SECONDARY_RELOAD_CLASS (CLASS, MODE, X)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* If either macro is defined, show that we need secondary reloads. */
|
|
|
|
#if defined(SECONDARY_INPUT_RELOAD_CLASS) || defined(SECONDARY_OUTPUT_RELOAD_CLASS)
|
|
|
|
#define HAVE_SECONDARY_RELOADS
|
|
|
|
#endif
|
|
|
|
|
1998-03-16 12:56:25 +01:00
|
|
|
/* If MEMORY_MOVE_COST isn't defined, give it a default here. */
|
|
|
|
#ifndef MEMORY_MOVE_COST
|
|
|
|
#ifdef HAVE_SECONDARY_RELOADS
|
|
|
|
#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
|
|
|
|
(4 + memory_move_secondary_cost ((MODE), (CLASS), (IN)))
|
|
|
|
#else
|
|
|
|
#define MEMORY_MOVE_COST(MODE,CLASS,IN) 4
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
extern int memory_move_secondary_cost PROTO ((enum machine_mode, enum reg_class, int));
|
|
|
|
|
1991-09-30 02:34:16 +01:00
|
|
|
/* See reload.c and reload1.c for comments on these variables. */
|
|
|
|
|
|
|
|
/* Maximum number of reloads we can need. */
|
|
|
|
#define MAX_RELOADS (2 * MAX_RECOG_OPERANDS * (MAX_REGS_PER_ADDRESS + 1))
|
|
|
|
|
1997-01-15 20:07:11 +01:00
|
|
|
extern enum reg_class reload_address_base_reg_class;
|
|
|
|
extern enum reg_class reload_address_index_reg_class;
|
1991-09-30 02:34:16 +01:00
|
|
|
extern rtx reload_in[MAX_RELOADS];
|
|
|
|
extern rtx reload_out[MAX_RELOADS];
|
|
|
|
extern rtx reload_in_reg[MAX_RELOADS];
|
Fix consistency problems with reg_equiv_{mem,address};
Improve reload inheritance;
* reload.c (reload_out_reg): New variable.
(loc_mentioned_in_p, remove_address_replacements): New functions.
(remove_replacements): Deleted.
(push_reload): Set reload_out_reg[i].
When merging, also set reload_{in,out}_reg[i], and remove
duplicate address reloads.
(combine_reloads): Copy reload_out_reg[i].
(find_reloads): Do make_memloc substitution also when
reg_equiv_memory_loc[regno] and num_not_at_initial_offset
are both nonzero.
Include *recog_operand_loc in commutativity operand changes.
Generate optional output reloads.
Delete reference to n_memlocs. Don't set *recog_operand_loc before
processing operands. Call make_memloc in reg_equiv_address code.
Set *recog_operand_loc only after processing operands, and only
if replace is true. Return a value.
When changing address reload types for operands that didn't get
reloaded, use RELOAD_FOR_OPADDR_ADDRESS for
RELOAD_FOR_INPADDR_ADDRESS / RELOAD_FOR_OUTADDR_ADDRESS reloads.
Don't emit USEs for pseudo SUBREGs when not replacing.
(find_reloads_address): Do make_memloc substitution also when
reg_equiv_memory_loc[regno] and num_not_at_initial_offset
are both nonzero.
(find_reloads_toplev): Likewise.
Call make_memloc in reg_equiv_address code.
(debug_reload_to_stream): Add code to output reload_out_reg.
(make_memloc): Delete local variable i, ifdefed out code, and
references to memlocs and n_memlocs.
(memlocs, n_memlocs): Delete.
(push_secondary_reload): Clear reload_out_reg.
(find_reloads_address_1): Provide memrefloc argument to all calls
to find_reloads_address.
In AUTO_INC code, handle non-directly addressable equivalences properly.
* reload.h (reload_out_reg, num_not_at_initial_offset): Declare.
(find_reloads): Add return type.
(remove_address_replacements, deallocate_reload_reg): Declare.
* reload1.c (num_not_at_initial_offset): No longer static.
(delete_address_reloads, delete_address_reloads_1): Likewise.
(deallocate_reload_reg): New function.
(spill_reg_stored_to): New array.
(eliminate_regs): Don't substitute from reg_equiv_memory_loc.
(eliminate_regs_in_insn): Move assignments of previous_offset and
max_offset fields, and recalculation of num_not_at_initial_offset
into new static function:
(update_eliminable_offsets) .
(reload_as_needed): Call update_eliminable_offsetss after calling
find_reloads.
Call forget_old_reloads_1 with contents of reloaded auto_inc
expressions if the actual addressing can't be changed to match the
auto_inc.
(choose_reload_regs): For inheritance, replace
reload_reg_free_before_p test with reload_reg_ions.
(emit_reload_insns): If reload_in is a MEM, set OLD to
reload_in_reg[j].
Don't reload directly from oldequiv; if it's a pseudo with a
stack slot, use reload_in[j].
Check that reload_in_reg[j] is a MEM before replacing reload_in
from reg_reloaded_contents.
Include non-spill registers in reload inheritance processing.
Also try to use reload_out_reg to set spill_reg_store /
reg_last_reload_reg.
In code to set new_spill_reg_store, use single_set to find out if
there is a single set.
Add code that allows to delete optional output reloads.
Add code to allow deletion of output reloads that use no spill reg.
At the end, set reload_override_in to oldequiv.
Also call delete_output_reload if reload_out_reg is equal to old
in oldequiv code.
Add code to call delete_output_reload for stores with no matching load.
Set / use spill_reg_stored_to.
Handle case where secondary output reload uses a temporary, but
actual store isn't found.
When looking for a store of a value not loaded in order to call
delete_output_reload, count_occurences should return 0 for no
loads; but discount inherited input reloadill_reg_stored_to.
Do checks for extra uses of REG. Changed all
callers.
Use delete_address_reloads.
(reload): Take return value of find_reloads into account.
If a no-op set needs more than one reload, delete it.
(reload_reg_free_before_p): RELOAD_FOR_INPUT
can ignore RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS
for the same operand.
(clear_reload_reg_in_use): Check for other reloads that keep a
register in use.
(reload_reg_free_for_value_p): handle RELOAD_FOR_OPERAND_ADDRESS /
RELOAD_FOR_OPADDR_ADDR.
Take into account when an address address reload is only needed
for the address reload we are considering.
(count_occurrences): Use rtx_equal_p for MEMs.
(inc_for_reload): Return instruction that stores into RELOADREG.
New argument two, IN, and rtx. Changed all callers.
(calculate_needs_all_insns, reload_as_needed):
Don't clear after_call for a CLOBBER.
Keep track of how many hard registers need to be copied from
after_call, and don't clear after_call before we have seen
that much copies, or we see a different instruction.
From-SVN: r23143
1998-10-16 21:54:38 +02:00
|
|
|
extern rtx reload_out_reg[MAX_RELOADS];
|
1991-09-30 02:34:16 +01:00
|
|
|
extern enum reg_class reload_reg_class[MAX_RELOADS];
|
|
|
|
extern enum machine_mode reload_inmode[MAX_RELOADS];
|
|
|
|
extern enum machine_mode reload_outmode[MAX_RELOADS];
|
|
|
|
extern char reload_optional[MAX_RELOADS];
|
1998-05-06 01:18:02 +02:00
|
|
|
extern char reload_nongroup[MAX_RELOADS];
|
1991-09-30 02:34:16 +01:00
|
|
|
extern int reload_inc[MAX_RELOADS];
|
1993-03-29 13:28:45 +02:00
|
|
|
extern int reload_opnum[MAX_RELOADS];
|
1991-09-30 02:34:16 +01:00
|
|
|
extern int reload_secondary_p[MAX_RELOADS];
|
1994-02-10 15:03:01 +01:00
|
|
|
extern int reload_secondary_in_reload[MAX_RELOADS];
|
|
|
|
extern int reload_secondary_out_reload[MAX_RELOADS];
|
1991-11-15 01:36:37 +01:00
|
|
|
#ifdef MAX_INSN_CODE
|
1994-02-10 15:03:01 +01:00
|
|
|
extern enum insn_code reload_secondary_in_icode[MAX_RELOADS];
|
|
|
|
extern enum insn_code reload_secondary_out_icode[MAX_RELOADS];
|
1991-11-15 01:36:37 +01:00
|
|
|
#endif
|
1991-09-30 02:34:16 +01:00
|
|
|
extern int n_reloads;
|
|
|
|
|
|
|
|
extern rtx reload_reg_rtx[MAX_RELOADS];
|
|
|
|
|
1993-03-29 13:28:45 +02:00
|
|
|
/* Encode the usage of a reload. The following codes are supported:
|
|
|
|
|
|
|
|
RELOAD_FOR_INPUT reload of an input operand
|
|
|
|
RELOAD_FOR_OUTPUT likewise, for output
|
|
|
|
RELOAD_FOR_INSN a reload that must not conflict with anything
|
|
|
|
used in the insn, but may conflict with
|
|
|
|
something used before or after the insn
|
|
|
|
RELOAD_FOR_INPUT_ADDRESS reload for parts of the address of an object
|
|
|
|
that is an input reload
|
1997-02-03 19:04:00 +01:00
|
|
|
RELOAD_FOR_INPADDR_ADDRESS reload needed for RELOAD_FOR_INPUT_ADDRESS
|
|
|
|
RELOAD_FOR_OUTPUT_ADDRESS like RELOAD_FOR INPUT_ADDRESS, for output
|
|
|
|
RELOAD_FOR_OUTADDR_ADDRESS reload needed for RELOAD_FOR_OUTPUT_ADDRESS
|
1993-03-29 13:28:45 +02:00
|
|
|
RELOAD_FOR_OPERAND_ADDRESS reload for the address of a non-reloaded
|
|
|
|
operand; these don't conflict with
|
|
|
|
any other addresses.
|
1994-06-14 23:36:02 +02:00
|
|
|
RELOAD_FOR_OPADDR_ADDR reload needed for RELOAD_FOR_OPERAND_ADDRESS
|
|
|
|
reloads; usually secondary reloads
|
1993-03-29 13:28:45 +02:00
|
|
|
RELOAD_OTHER none of the above, usually multiple uses
|
|
|
|
RELOAD_FOR_OTHER_ADDRESS reload for part of the address of an input
|
|
|
|
that is marked RELOAD_OTHER.
|
|
|
|
|
|
|
|
This used to be "enum reload_when_needed" but some debuggers have trouble
|
|
|
|
with an enum tag and variable of the same name. */
|
|
|
|
|
|
|
|
enum reload_type
|
1991-09-30 02:34:16 +01:00
|
|
|
{
|
1993-03-29 13:28:45 +02:00
|
|
|
RELOAD_FOR_INPUT, RELOAD_FOR_OUTPUT, RELOAD_FOR_INSN,
|
1997-02-03 19:04:00 +01:00
|
|
|
RELOAD_FOR_INPUT_ADDRESS, RELOAD_FOR_INPADDR_ADDRESS,
|
|
|
|
RELOAD_FOR_OUTPUT_ADDRESS, RELOAD_FOR_OUTADDR_ADDRESS,
|
1994-06-14 23:36:02 +02:00
|
|
|
RELOAD_FOR_OPERAND_ADDRESS, RELOAD_FOR_OPADDR_ADDR,
|
|
|
|
RELOAD_OTHER, RELOAD_FOR_OTHER_ADDRESS
|
1991-09-30 02:34:16 +01:00
|
|
|
};
|
|
|
|
|
1993-03-29 13:28:45 +02:00
|
|
|
extern enum reload_type reload_when_needed[MAX_RELOADS];
|
1991-09-30 02:34:16 +01:00
|
|
|
|
|
|
|
extern rtx *reg_equiv_constant;
|
1992-05-22 23:20:28 +02:00
|
|
|
extern rtx *reg_equiv_memory_loc;
|
1991-09-30 02:34:16 +01:00
|
|
|
extern rtx *reg_equiv_address;
|
|
|
|
extern rtx *reg_equiv_mem;
|
|
|
|
|
|
|
|
/* All the "earlyclobber" operands of the current insn
|
|
|
|
are recorded here. */
|
|
|
|
extern int n_earlyclobbers;
|
|
|
|
extern rtx reload_earlyclobbers[MAX_RECOG_OPERANDS];
|
|
|
|
|
1993-03-29 13:28:45 +02:00
|
|
|
/* Save the number of operands. */
|
|
|
|
extern int reload_n_operands;
|
|
|
|
|
1991-09-30 02:34:16 +01:00
|
|
|
/* First uid used by insns created by reload in this function.
|
|
|
|
Used in find_equiv_reg. */
|
|
|
|
extern int reload_first_uid;
|
|
|
|
|
|
|
|
/* Nonzero if indirect addressing is supported when the innermost MEM is
|
|
|
|
of the form (MEM (SYMBOL_REF sym)). It is assumed that the level to
|
|
|
|
which these are valid is the same as spill_indirect_levels, above. */
|
|
|
|
|
|
|
|
extern char indirect_symref_ok;
|
|
|
|
|
|
|
|
/* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid. */
|
|
|
|
extern char double_reg_address_ok;
|
|
|
|
|
Fix consistency problems with reg_equiv_{mem,address};
Improve reload inheritance;
* reload.c (reload_out_reg): New variable.
(loc_mentioned_in_p, remove_address_replacements): New functions.
(remove_replacements): Deleted.
(push_reload): Set reload_out_reg[i].
When merging, also set reload_{in,out}_reg[i], and remove
duplicate address reloads.
(combine_reloads): Copy reload_out_reg[i].
(find_reloads): Do make_memloc substitution also when
reg_equiv_memory_loc[regno] and num_not_at_initial_offset
are both nonzero.
Include *recog_operand_loc in commutativity operand changes.
Generate optional output reloads.
Delete reference to n_memlocs. Don't set *recog_operand_loc before
processing operands. Call make_memloc in reg_equiv_address code.
Set *recog_operand_loc only after processing operands, and only
if replace is true. Return a value.
When changing address reload types for operands that didn't get
reloaded, use RELOAD_FOR_OPADDR_ADDRESS for
RELOAD_FOR_INPADDR_ADDRESS / RELOAD_FOR_OUTADDR_ADDRESS reloads.
Don't emit USEs for pseudo SUBREGs when not replacing.
(find_reloads_address): Do make_memloc substitution also when
reg_equiv_memory_loc[regno] and num_not_at_initial_offset
are both nonzero.
(find_reloads_toplev): Likewise.
Call make_memloc in reg_equiv_address code.
(debug_reload_to_stream): Add code to output reload_out_reg.
(make_memloc): Delete local variable i, ifdefed out code, and
references to memlocs and n_memlocs.
(memlocs, n_memlocs): Delete.
(push_secondary_reload): Clear reload_out_reg.
(find_reloads_address_1): Provide memrefloc argument to all calls
to find_reloads_address.
In AUTO_INC code, handle non-directly addressable equivalences properly.
* reload.h (reload_out_reg, num_not_at_initial_offset): Declare.
(find_reloads): Add return type.
(remove_address_replacements, deallocate_reload_reg): Declare.
* reload1.c (num_not_at_initial_offset): No longer static.
(delete_address_reloads, delete_address_reloads_1): Likewise.
(deallocate_reload_reg): New function.
(spill_reg_stored_to): New array.
(eliminate_regs): Don't substitute from reg_equiv_memory_loc.
(eliminate_regs_in_insn): Move assignments of previous_offset and
max_offset fields, and recalculation of num_not_at_initial_offset
into new static function:
(update_eliminable_offsets) .
(reload_as_needed): Call update_eliminable_offsetss after calling
find_reloads.
Call forget_old_reloads_1 with contents of reloaded auto_inc
expressions if the actual addressing can't be changed to match the
auto_inc.
(choose_reload_regs): For inheritance, replace
reload_reg_free_before_p test with reload_reg_ions.
(emit_reload_insns): If reload_in is a MEM, set OLD to
reload_in_reg[j].
Don't reload directly from oldequiv; if it's a pseudo with a
stack slot, use reload_in[j].
Check that reload_in_reg[j] is a MEM before replacing reload_in
from reg_reloaded_contents.
Include non-spill registers in reload inheritance processing.
Also try to use reload_out_reg to set spill_reg_store /
reg_last_reload_reg.
In code to set new_spill_reg_store, use single_set to find out if
there is a single set.
Add code that allows to delete optional output reloads.
Add code to allow deletion of output reloads that use no spill reg.
At the end, set reload_override_in to oldequiv.
Also call delete_output_reload if reload_out_reg is equal to old
in oldequiv code.
Add code to call delete_output_reload for stores with no matching load.
Set / use spill_reg_stored_to.
Handle case where secondary output reload uses a temporary, but
actual store isn't found.
When looking for a store of a value not loaded in order to call
delete_output_reload, count_occurences should return 0 for no
loads; but discount inherited input reloadill_reg_stored_to.
Do checks for extra uses of REG. Changed all
callers.
Use delete_address_reloads.
(reload): Take return value of find_reloads into account.
If a no-op set needs more than one reload, delete it.
(reload_reg_free_before_p): RELOAD_FOR_INPUT
can ignore RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS
for the same operand.
(clear_reload_reg_in_use): Check for other reloads that keep a
register in use.
(reload_reg_free_for_value_p): handle RELOAD_FOR_OPERAND_ADDRESS /
RELOAD_FOR_OPADDR_ADDR.
Take into account when an address address reload is only needed
for the address reload we are considering.
(count_occurrences): Use rtx_equal_p for MEMs.
(inc_for_reload): Return instruction that stores into RELOADREG.
New argument two, IN, and rtx. Changed all callers.
(calculate_needs_all_insns, reload_as_needed):
Don't clear after_call for a CLOBBER.
Keep track of how many hard registers need to be copied from
after_call, and don't clear after_call before we have seen
that much copies, or we see a different instruction.
From-SVN: r23143
1998-10-16 21:54:38 +02:00
|
|
|
extern int num_not_at_initial_offset;
|
|
|
|
|
1991-11-15 01:36:37 +01:00
|
|
|
#ifdef MAX_INSN_CODE
|
|
|
|
/* These arrays record the insn_code of insns that may be needed to
|
|
|
|
perform input and output reloads of special objects. They provide a
|
|
|
|
place to pass a scratch register. */
|
|
|
|
extern enum insn_code reload_in_optab[];
|
|
|
|
extern enum insn_code reload_out_optab[];
|
|
|
|
#endif
|
|
|
|
|
Makefile.in (stupid.o): Update dependencies.
* Makefile.in (stupid.o): Update dependencies.
(global.o): Likewise.
* global.c: Include reload.h
(reg_becomes_live): New function.
(reg_dies): New function.
(build_insn_chain): New function.
(global_alloc): Call build_insn_chain before calling reload.
* reload.h (struct needs): New structure definition.
(struct insn_chain): Likewise.
(reload_insn_chain): Declare variable.
(new_insn_chain): Declare function.
* reload1.c (reload_startobj): New variable.
(reload_insn_chain): New variable.
(unused_insn_chains): New variable.
(new_insn_chain): New function.
(init_reload): Initialize reload_startobj, not reload_firstobj.
(reload): Initialize reload_firstobj.
Before returning, free everything on the reload_obstack.
* stupid.c: Include insn-config.h, reload.h and basic-block.h.
(reg_where_dead_chain, reg_where_born_exact, reg_where_born_clobber,
current_chain): New variables.
(reg_where_born): Delete variable.
(REG_WHERE_BORN): New macro.
(find_clobbered_regs): New function.
(stupid_life_analysis): Don't allocate/free reg_where_born.
Allocate and free reg_where_born_exact, reg_where_born_clobber,
reg_where_dead_chain.
Use REG_WHERE_BORN instead of reg_where_born.
While processing the insns, build the reload_insn_chain with
information about register lifetimes.
(stupid_reg_compare): Use REG_WHERE_BORN instead of reg_where_born.
(stupid_mark_refs): Replace arg INSN with arg CHAIN. All callers
changed.
Compute and information about birth and death of pseudo registers in
reg_where_dead_chain, reg_where_born_exact and reg_where_born_clobber.
Delete code to set elements of reg_where_born.
From-SVN: r22862
1998-10-06 02:39:23 +02:00
|
|
|
struct needs
|
|
|
|
{
|
|
|
|
/* [0] is normal, [1] is nongroup. */
|
|
|
|
short regs[2][N_REG_CLASSES];
|
|
|
|
short groups[N_REG_CLASSES];
|
|
|
|
};
|
|
|
|
|
|
|
|
#if defined SET_HARD_REG_BIT && defined CLEAR_REG_SET
|
|
|
|
/* This structure describes instructions which are relevant for reload.
|
|
|
|
Apart from all regular insns, this also includes CODE_LABELs, since they
|
|
|
|
must be examined for register elimination. */
|
|
|
|
struct insn_chain
|
|
|
|
{
|
|
|
|
/* Links to the neighbour instructions. */
|
|
|
|
struct insn_chain *next, *prev;
|
|
|
|
|
|
|
|
/* Link through a chains set up by calculate_needs_all_insns, containing
|
|
|
|
all insns that need reloading. */
|
|
|
|
struct insn_chain *next_need_reload;
|
|
|
|
|
|
|
|
/* The basic block this insn is in. */
|
|
|
|
int block;
|
|
|
|
/* The rtx of the insn. */
|
|
|
|
rtx insn;
|
|
|
|
/* Register life information: record all live hard registers, and all
|
|
|
|
live pseudos that have a hard register.
|
|
|
|
This information is recorded for the point immediately before the insn
|
|
|
|
(in live_before), and for the point within the insn at which all
|
|
|
|
outputs have just been written to (in live_after). */
|
|
|
|
regset live_before;
|
|
|
|
regset live_after;
|
|
|
|
|
|
|
|
/* For each class, size of group of consecutive regs
|
|
|
|
that is needed for the reloads of this class. */
|
|
|
|
char group_size[N_REG_CLASSES];
|
|
|
|
/* For each class, the machine mode which requires consecutive
|
|
|
|
groups of regs of that class.
|
|
|
|
If two different modes ever require groups of one class,
|
|
|
|
they must be the same size and equally restrictive for that class,
|
|
|
|
otherwise we can't handle the complexity. */
|
|
|
|
enum machine_mode group_mode[N_REG_CLASSES];
|
|
|
|
|
|
|
|
/* Indicates if a register was counted against the need for
|
|
|
|
groups. 0 means it can count against max_nongroup instead. */
|
|
|
|
HARD_REG_SET counted_for_groups;
|
|
|
|
|
|
|
|
/* Indicates if a register was counted against the need for
|
|
|
|
non-groups. 0 means it can become part of a new group.
|
|
|
|
During choose_reload_regs, 1 here means don't use this reg
|
|
|
|
as part of a group, even if it seems to be otherwise ok. */
|
|
|
|
HARD_REG_SET counted_for_nongroups;
|
|
|
|
|
|
|
|
/* Indicates which registers have already been used for spills. */
|
|
|
|
HARD_REG_SET used_spill_regs;
|
|
|
|
|
|
|
|
/* Describe the needs for reload registers of this insn. */
|
|
|
|
struct needs need;
|
|
|
|
|
|
|
|
/* Nonzero if find_reloads said the insn requires reloading. */
|
|
|
|
unsigned int need_reload:1;
|
|
|
|
/* Nonzero if eliminate_regs_in_insn said it requires eliminations. */
|
|
|
|
unsigned int need_elim:1;
|
|
|
|
/* Nonzero if this insn was inserted by perform_caller_saves. */
|
|
|
|
unsigned int is_caller_save_insn:1;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* A chain of insn_chain structures to describe all non-note insns in
|
|
|
|
a function. */
|
|
|
|
extern struct insn_chain *reload_insn_chain;
|
|
|
|
|
|
|
|
/* Allocate a new insn_chain structure. */
|
|
|
|
extern struct insn_chain *new_insn_chain PROTO((void));
|
|
|
|
|
1998-10-14 03:14:42 +02:00
|
|
|
extern void compute_use_by_pseudos PROTO((HARD_REG_SET *, regset));
|
Makefile.in (stupid.o): Update dependencies.
* Makefile.in (stupid.o): Update dependencies.
(global.o): Likewise.
* global.c: Include reload.h
(reg_becomes_live): New function.
(reg_dies): New function.
(build_insn_chain): New function.
(global_alloc): Call build_insn_chain before calling reload.
* reload.h (struct needs): New structure definition.
(struct insn_chain): Likewise.
(reload_insn_chain): Declare variable.
(new_insn_chain): Declare function.
* reload1.c (reload_startobj): New variable.
(reload_insn_chain): New variable.
(unused_insn_chains): New variable.
(new_insn_chain): New function.
(init_reload): Initialize reload_startobj, not reload_firstobj.
(reload): Initialize reload_firstobj.
Before returning, free everything on the reload_obstack.
* stupid.c: Include insn-config.h, reload.h and basic-block.h.
(reg_where_dead_chain, reg_where_born_exact, reg_where_born_clobber,
current_chain): New variables.
(reg_where_born): Delete variable.
(REG_WHERE_BORN): New macro.
(find_clobbered_regs): New function.
(stupid_life_analysis): Don't allocate/free reg_where_born.
Allocate and free reg_where_born_exact, reg_where_born_clobber,
reg_where_dead_chain.
Use REG_WHERE_BORN instead of reg_where_born.
While processing the insns, build the reload_insn_chain with
information about register lifetimes.
(stupid_reg_compare): Use REG_WHERE_BORN instead of reg_where_born.
(stupid_mark_refs): Replace arg INSN with arg CHAIN. All callers
changed.
Compute and information about birth and death of pseudo registers in
reg_where_dead_chain, reg_where_born_exact and reg_where_born_clobber.
Delete code to set elements of reg_where_born.
From-SVN: r22862
1998-10-06 02:39:23 +02:00
|
|
|
#endif
|
|
|
|
|
1993-03-29 13:28:45 +02:00
|
|
|
/* Functions from reload.c: */
|
|
|
|
|
|
|
|
/* Return a memory location that will be used to copy X in mode MODE.
|
|
|
|
If we haven't already made a location for this mode in this insn,
|
|
|
|
call find_reloads_address on the location being returned. */
|
|
|
|
extern rtx get_secondary_mem PROTO((rtx, enum machine_mode,
|
|
|
|
int, enum reload_type));
|
|
|
|
|
|
|
|
/* Clear any secondary memory locations we've made. */
|
|
|
|
extern void clear_secondary_mem PROTO((void));
|
|
|
|
|
|
|
|
/* Transfer all replacements that used to be in reload FROM to be in
|
|
|
|
reload TO. */
|
|
|
|
extern void transfer_replacements PROTO((int, int));
|
|
|
|
|
Fix consistency problems with reg_equiv_{mem,address};
Improve reload inheritance;
* reload.c (reload_out_reg): New variable.
(loc_mentioned_in_p, remove_address_replacements): New functions.
(remove_replacements): Deleted.
(push_reload): Set reload_out_reg[i].
When merging, also set reload_{in,out}_reg[i], and remove
duplicate address reloads.
(combine_reloads): Copy reload_out_reg[i].
(find_reloads): Do make_memloc substitution also when
reg_equiv_memory_loc[regno] and num_not_at_initial_offset
are both nonzero.
Include *recog_operand_loc in commutativity operand changes.
Generate optional output reloads.
Delete reference to n_memlocs. Don't set *recog_operand_loc before
processing operands. Call make_memloc in reg_equiv_address code.
Set *recog_operand_loc only after processing operands, and only
if replace is true. Return a value.
When changing address reload types for operands that didn't get
reloaded, use RELOAD_FOR_OPADDR_ADDRESS for
RELOAD_FOR_INPADDR_ADDRESS / RELOAD_FOR_OUTADDR_ADDRESS reloads.
Don't emit USEs for pseudo SUBREGs when not replacing.
(find_reloads_address): Do make_memloc substitution also when
reg_equiv_memory_loc[regno] and num_not_at_initial_offset
are both nonzero.
(find_reloads_toplev): Likewise.
Call make_memloc in reg_equiv_address code.
(debug_reload_to_stream): Add code to output reload_out_reg.
(make_memloc): Delete local variable i, ifdefed out code, and
references to memlocs and n_memlocs.
(memlocs, n_memlocs): Delete.
(push_secondary_reload): Clear reload_out_reg.
(find_reloads_address_1): Provide memrefloc argument to all calls
to find_reloads_address.
In AUTO_INC code, handle non-directly addressable equivalences properly.
* reload.h (reload_out_reg, num_not_at_initial_offset): Declare.
(find_reloads): Add return type.
(remove_address_replacements, deallocate_reload_reg): Declare.
* reload1.c (num_not_at_initial_offset): No longer static.
(delete_address_reloads, delete_address_reloads_1): Likewise.
(deallocate_reload_reg): New function.
(spill_reg_stored_to): New array.
(eliminate_regs): Don't substitute from reg_equiv_memory_loc.
(eliminate_regs_in_insn): Move assignments of previous_offset and
max_offset fields, and recalculation of num_not_at_initial_offset
into new static function:
(update_eliminable_offsets) .
(reload_as_needed): Call update_eliminable_offsetss after calling
find_reloads.
Call forget_old_reloads_1 with contents of reloaded auto_inc
expressions if the actual addressing can't be changed to match the
auto_inc.
(choose_reload_regs): For inheritance, replace
reload_reg_free_before_p test with reload_reg_ions.
(emit_reload_insns): If reload_in is a MEM, set OLD to
reload_in_reg[j].
Don't reload directly from oldequiv; if it's a pseudo with a
stack slot, use reload_in[j].
Check that reload_in_reg[j] is a MEM before replacing reload_in
from reg_reloaded_contents.
Include non-spill registers in reload inheritance processing.
Also try to use reload_out_reg to set spill_reg_store /
reg_last_reload_reg.
In code to set new_spill_reg_store, use single_set to find out if
there is a single set.
Add code that allows to delete optional output reloads.
Add code to allow deletion of output reloads that use no spill reg.
At the end, set reload_override_in to oldequiv.
Also call delete_output_reload if reload_out_reg is equal to old
in oldequiv code.
Add code to call delete_output_reload for stores with no matching load.
Set / use spill_reg_stored_to.
Handle case where secondary output reload uses a temporary, but
actual store isn't found.
When looking for a store of a value not loaded in order to call
delete_output_reload, count_occurences should return 0 for no
loads; but discount inherited input reloadill_reg_stored_to.
Do checks for extra uses of REG. Changed all
callers.
Use delete_address_reloads.
(reload): Take return value of find_reloads into account.
If a no-op set needs more than one reload, delete it.
(reload_reg_free_before_p): RELOAD_FOR_INPUT
can ignore RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS
for the same operand.
(clear_reload_reg_in_use): Check for other reloads that keep a
register in use.
(reload_reg_free_for_value_p): handle RELOAD_FOR_OPERAND_ADDRESS /
RELOAD_FOR_OPADDR_ADDR.
Take into account when an address address reload is only needed
for the address reload we are considering.
(count_occurrences): Use rtx_equal_p for MEMs.
(inc_for_reload): Return instruction that stores into RELOADREG.
New argument two, IN, and rtx. Changed all callers.
(calculate_needs_all_insns, reload_as_needed):
Don't clear after_call for a CLOBBER.
Keep track of how many hard registers need to be copied from
after_call, and don't clear after_call before we have seen
that much copies, or we see a different instruction.
From-SVN: r23143
1998-10-16 21:54:38 +02:00
|
|
|
/* IN_RTX is the value loaded by a reload that we now decided to inherit,
|
|
|
|
or a subpart of it. If we have any replacements registered for IN_RTX,
|
|
|
|
chancel the reloads that were supposed to load them.
|
|
|
|
Return non-zero if we chanceled any reloads. */
|
|
|
|
extern int remove_address_replacements PROTO((rtx in_rtx));
|
1998-05-14 02:44:02 +02:00
|
|
|
|
1993-03-29 13:28:45 +02:00
|
|
|
/* Like rtx_equal_p except that it allows a REG and a SUBREG to match
|
|
|
|
if they are the same hard reg, and has special hacks for
|
|
|
|
autoincrement and autodecrement. */
|
|
|
|
extern int operands_match_p PROTO((rtx, rtx));
|
|
|
|
|
|
|
|
/* Return 1 if altering OP will not modify the value of CLOBBER. */
|
|
|
|
extern int safe_from_earlyclobber PROTO((rtx, rtx));
|
|
|
|
|
|
|
|
/* Search the body of INSN for values that need reloading and record them
|
|
|
|
with push_reload. REPLACE nonzero means record also where the values occur
|
1993-05-09 07:08:34 +02:00
|
|
|
so that subst_reloads can be used. */
|
Fix consistency problems with reg_equiv_{mem,address};
Improve reload inheritance;
* reload.c (reload_out_reg): New variable.
(loc_mentioned_in_p, remove_address_replacements): New functions.
(remove_replacements): Deleted.
(push_reload): Set reload_out_reg[i].
When merging, also set reload_{in,out}_reg[i], and remove
duplicate address reloads.
(combine_reloads): Copy reload_out_reg[i].
(find_reloads): Do make_memloc substitution also when
reg_equiv_memory_loc[regno] and num_not_at_initial_offset
are both nonzero.
Include *recog_operand_loc in commutativity operand changes.
Generate optional output reloads.
Delete reference to n_memlocs. Don't set *recog_operand_loc before
processing operands. Call make_memloc in reg_equiv_address code.
Set *recog_operand_loc only after processing operands, and only
if replace is true. Return a value.
When changing address reload types for operands that didn't get
reloaded, use RELOAD_FOR_OPADDR_ADDRESS for
RELOAD_FOR_INPADDR_ADDRESS / RELOAD_FOR_OUTADDR_ADDRESS reloads.
Don't emit USEs for pseudo SUBREGs when not replacing.
(find_reloads_address): Do make_memloc substitution also when
reg_equiv_memory_loc[regno] and num_not_at_initial_offset
are both nonzero.
(find_reloads_toplev): Likewise.
Call make_memloc in reg_equiv_address code.
(debug_reload_to_stream): Add code to output reload_out_reg.
(make_memloc): Delete local variable i, ifdefed out code, and
references to memlocs and n_memlocs.
(memlocs, n_memlocs): Delete.
(push_secondary_reload): Clear reload_out_reg.
(find_reloads_address_1): Provide memrefloc argument to all calls
to find_reloads_address.
In AUTO_INC code, handle non-directly addressable equivalences properly.
* reload.h (reload_out_reg, num_not_at_initial_offset): Declare.
(find_reloads): Add return type.
(remove_address_replacements, deallocate_reload_reg): Declare.
* reload1.c (num_not_at_initial_offset): No longer static.
(delete_address_reloads, delete_address_reloads_1): Likewise.
(deallocate_reload_reg): New function.
(spill_reg_stored_to): New array.
(eliminate_regs): Don't substitute from reg_equiv_memory_loc.
(eliminate_regs_in_insn): Move assignments of previous_offset and
max_offset fields, and recalculation of num_not_at_initial_offset
into new static function:
(update_eliminable_offsets) .
(reload_as_needed): Call update_eliminable_offsetss after calling
find_reloads.
Call forget_old_reloads_1 with contents of reloaded auto_inc
expressions if the actual addressing can't be changed to match the
auto_inc.
(choose_reload_regs): For inheritance, replace
reload_reg_free_before_p test with reload_reg_ions.
(emit_reload_insns): If reload_in is a MEM, set OLD to
reload_in_reg[j].
Don't reload directly from oldequiv; if it's a pseudo with a
stack slot, use reload_in[j].
Check that reload_in_reg[j] is a MEM before replacing reload_in
from reg_reloaded_contents.
Include non-spill registers in reload inheritance processing.
Also try to use reload_out_reg to set spill_reg_store /
reg_last_reload_reg.
In code to set new_spill_reg_store, use single_set to find out if
there is a single set.
Add code that allows to delete optional output reloads.
Add code to allow deletion of output reloads that use no spill reg.
At the end, set reload_override_in to oldequiv.
Also call delete_output_reload if reload_out_reg is equal to old
in oldequiv code.
Add code to call delete_output_reload for stores with no matching load.
Set / use spill_reg_stored_to.
Handle case where secondary output reload uses a temporary, but
actual store isn't found.
When looking for a store of a value not loaded in order to call
delete_output_reload, count_occurences should return 0 for no
loads; but discount inherited input reloadill_reg_stored_to.
Do checks for extra uses of REG. Changed all
callers.
Use delete_address_reloads.
(reload): Take return value of find_reloads into account.
If a no-op set needs more than one reload, delete it.
(reload_reg_free_before_p): RELOAD_FOR_INPUT
can ignore RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS
for the same operand.
(clear_reload_reg_in_use): Check for other reloads that keep a
register in use.
(reload_reg_free_for_value_p): handle RELOAD_FOR_OPERAND_ADDRESS /
RELOAD_FOR_OPADDR_ADDR.
Take into account when an address address reload is only needed
for the address reload we are considering.
(count_occurrences): Use rtx_equal_p for MEMs.
(inc_for_reload): Return instruction that stores into RELOADREG.
New argument two, IN, and rtx. Changed all callers.
(calculate_needs_all_insns, reload_as_needed):
Don't clear after_call for a CLOBBER.
Keep track of how many hard registers need to be copied from
after_call, and don't clear after_call before we have seen
that much copies, or we see a different instruction.
From-SVN: r23143
1998-10-16 21:54:38 +02:00
|
|
|
extern int find_reloads PROTO((rtx, int, int, int, short *));
|
1993-03-29 13:28:45 +02:00
|
|
|
|
|
|
|
/* Compute the sum of X and Y, making canonicalizations assumed in an
|
|
|
|
address, namely: sum constant integers, surround the sum of two
|
|
|
|
constants with a CONST, put the constant as the second operand, and
|
|
|
|
group the constant on the outermost sum. */
|
|
|
|
extern rtx form_sum PROTO((rtx, rtx));
|
|
|
|
|
|
|
|
/* Substitute into the current INSN the registers into which we have reloaded
|
|
|
|
the things that need reloading. */
|
1993-03-20 03:17:20 +01:00
|
|
|
extern void subst_reloads PROTO((void));
|
1993-03-29 13:28:45 +02:00
|
|
|
|
|
|
|
/* Make a copy of any replacements being done into X and move those copies
|
|
|
|
to locations in Y, a copy of X. We only look at the highest level of
|
|
|
|
the RTL. */
|
|
|
|
extern void copy_replacements PROTO((rtx, rtx));
|
|
|
|
|
1998-04-02 04:42:26 +02:00
|
|
|
/* Change any replacements being done to *X to be done to *Y */
|
|
|
|
extern void move_replacements PROTO((rtx *x, rtx *y));
|
|
|
|
|
1993-03-29 13:28:45 +02:00
|
|
|
/* If LOC was scheduled to be replaced by something, return the replacement.
|
|
|
|
Otherwise, return *LOC. */
|
1993-03-20 03:17:20 +01:00
|
|
|
extern rtx find_replacement PROTO((rtx *));
|
1993-03-29 13:28:45 +02:00
|
|
|
|
|
|
|
/* Return nonzero if register in range [REGNO, ENDREGNO)
|
|
|
|
appears either explicitly or implicitly in X
|
|
|
|
other than being stored into. */
|
|
|
|
extern int refers_to_regno_for_reload_p PROTO((int, int, rtx, rtx *));
|
|
|
|
|
|
|
|
/* Nonzero if modifying X will affect IN. */
|
|
|
|
extern int reg_overlap_mentioned_for_reload_p PROTO((rtx, rtx));
|
|
|
|
|
|
|
|
/* Return nonzero if anything in X contains a MEM. Look also for pseudo
|
|
|
|
registers. */
|
|
|
|
extern int refers_to_mem_for_reload_p PROTO((rtx));
|
|
|
|
|
|
|
|
/* Check the insns before INSN to see if there is a suitable register
|
|
|
|
containing the same value as GOAL. */
|
|
|
|
extern rtx find_equiv_reg PROTO((rtx, rtx, enum reg_class, int, short *,
|
|
|
|
int, enum machine_mode));
|
|
|
|
|
|
|
|
/* Return 1 if register REGNO is the subject of a clobber in insn INSN. */
|
|
|
|
extern int regno_clobbered_p PROTO((int, rtx));
|
|
|
|
|
|
|
|
/* Functions in reload1.c: */
|
|
|
|
|
Warning fixes:
* Makefile.in (c-lang.o): Depend on c-tree.h, c-lex.h and toplev.h.
(c-lex.o): Depend on output.h.
(c-common.o): Likewise.
(stmt.o): Likewise.
(calls.o): Likewise.
(integrate.o): Depend on toplev.h.
(regclass.o): Depend on output.h.
(final.o): Depend on reload.h.
* c-common.c: Include output.h.
(check_format_info): Remove unused variable `integral_format'.
* c-decl.c (print_lang_decl): Mark parameters `file', `node' and
`indent' with ATTRIBUTE_UNUSED.
(print_lang_type): Likewise.
(maybe_build_cleanup): Likewise for parameter `decl'.
(copy_lang_decl): Likewise for parameter `node'.
* c-lang.c: Include c-tree.h, c-lex.h and toplev.h.
(lang_print_xnode): Mark parameters `file', `node' and `indent'
with ATTRIBUTE_UNUSED.
(lookup_interface): Likewise for parameter `arg'.
(is_class_name): Likewise.
(maybe_objc_check_decl): Likewise for parameter `decl'.
(maybe_objc_comptypes): Likewise for parameters `lhs', `rhs' and
`reflexive'.
(maybe_objc_method_name): Likewise for parameter `decl'.
(build_objc_string): Likewise for parameters `len' and `str'.
* c-lex.c: Include output.h.
* c-lex.h (position_after_white_space): Correct typo in prototype.
* c-tree.h (finish_file, c_expand_start_cond, c_expand_start_else,
c_expand_end_cond, init_iterators): Add prototypes.
* caller-save.c (set_reg_live): Mark parameters `reg' and `setter'
with ATTRIBUTE_UNUSED.
* calls.c: Include output.h.
* cccp.c (pipe_closed): Mark parameter `signo' with
ATTRIBUTE_UNUSED.
* combine.c: Move inclusion of expr.h to after insn-config.h.
* iris6.h (ASM_IDENTIFY_GCC, ASM_IDENTIFY_LANGUAGE): Don't define
as empty, rather define as ((void)0).
* sparc.c (sparc_check_64): Add braces around ambiguous `else'.
Add parentheses around assignment used as truth value.
* cplus-dem.c (squangle_mop_up): Change return type to void.
(internal_cplus_demangle): Remove unused parameter `options'.
All callers changed.
(cplus_demangle_opname): Remove function wide variable `int i' and
replace with `size_t i' at each location where it is used.
(cplus_demangle_opname): change type of `i' from int to size_t.
* cppexp.c (right_shift): Mark parameter `pfile' with
ATTRIBUTE_UNUSED.
* cpphash.c (cpp_lookup): Likewise.
(cpp_hash_cleanup): Likewise.
* cpplib.c (parse_name): Add a prototype and make it static.
(null_underflow): Mark parameter `pfile' with ATTRIBUTE_UNUSED.
(null_cleanup): Likewise for parameters `pbuf' and `pfile'.
(macro_cleanup): Likewise for parameter `pfile'.
(file_cleanup): Likewise.
* cpplib.h (cpp_reader_init, cpp_options_init, cpp_start_read,
cpp_read_check_assertion, skip_rest_of_line): Add prototypes.
* crtstuff.c (force_to_data, __CTOR_LIST__, force_to_data,
__DTOR_END__, __FRAME_END__): Mark with ATTRIBUTE_UNUSED.
* cse.c (cse_check_loop_start): Mark parameter `set' with
ATTRIBUTE_UNUSED.
* dbxout.c (flag_minimal_debug, have_used_extensions,
source_label_number): Move inside macro wrapper check against
defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO).
* dwarf2out.c (gen_entry_point_die): Hide prototype and definition.
* except.h (doing_eh): Provide prototype.
* expr.c: Move inclusion of expr.h to after insn-config.h.
* final.c: Include reload.h.
(shorten_branches): Cast the first argument of bzero to char *.
* fix-header.c (cpp_print_containing_files): Mark parameter
`pfile' with ATTRIBUTE_UNUSED.
(cpp_fatal): Likewise.
* flow.c (find_basic_blocks_1): Cast the first argument of bzero
to char *.
* genattrtab.c (make_length_attrs): Change the type of variable
`i' from int to size_t.
(zero_fn): Mark parameter `exp' with ATTRIBUTE_UNUSED.
(one_fn): Likewise.
* genextract.c (main): When generating insn-extract.c, mark
variable `junk' with ATTRIBUTE_UNUSED.
* gengenrtl.c (gencode): When generating genrtl.c, cast the first
argument of bzero to char*.
* integrate.c: Include toplev.h.
* libgcc2.c: Wrap `struct exception_table' and
`find_exception_handler' in macro DWARF2_UNWIND_INFO.
* objc/Make-lang.in (objc-act.o): Depend on toplev.h.
* objc/objc-act.c: Include toplev.h.
(lang_print_xnode): Mark parameters `file', `node' and `indent'
with ATTRIBUTE_UNUSED.
(finish_protocol): Likewise for parameter `protocol'.
* output.h (declare_weak): Add prototype.
(decode_reg_name): Don't wrap with TREE_CODE macro.
(assemble_alias): Add prototype.
* regclass.c: Include output.h.
* reload.h (reloads_conflict): Add prototype.
* rtl.h (print_rtl_single, mark_elimiation, reg_class_subset_p,
output_func_start_profiler): Add prototypes.
* rtlanal.c (reg_set_p_1): Mark parameters `x' and `pat' with
ATTRIBUTE_UNUSED.
* scan-decls.c: Include scan.h.
* scan.h (recognized_function, recognized_extern): Add prototypes.
* stmt.c: Include output.h.
* toplev.c (error_for_asm, warning_for_asm): Remove prototypes.
(output_lang_identify): Hide prototype and definition.
(float_signal): Mark parameter `signo' with ATTRIBUTE_UNUSED.
(pipe_closed): Likewise.
* toplev.h (count_error, strip_off_ending, error_for_asm,
warning_for_asm): Add prototypes.
From-SVN: r19712
1998-05-13 14:40:39 +02:00
|
|
|
extern int reloads_conflict PROTO ((int, int));
|
|
|
|
|
1998-01-10 21:54:37 +01:00
|
|
|
int count_occurrences PROTO((rtx, rtx));
|
|
|
|
|
1993-03-29 13:28:45 +02:00
|
|
|
/* Initialize the reload pass once per compilation. */
|
|
|
|
extern void init_reload PROTO((void));
|
|
|
|
|
|
|
|
/* The reload pass itself. */
|
reload.h, [...]: Revert March 15 change.
* reload.h, reload1.c (eliminate_regs), caller-save.c, dbxout.c,
dwarfout.c, dwarf2out.c, reload.c, sdbout.c: Revert March 15 change.
* reload.c (push_reload): If WORD_REGISTER_OPERATIONS, reload the
SUBREG_REG if the word count is unchanged.
* reload1.c (eliminate_regs) [case SET]: If W_R_O, preserve
subregs of identical word size for push_reload.
From-SVN: r17105
1997-12-15 18:55:58 +01:00
|
|
|
extern int reload PROTO((rtx, int, FILE *));
|
1993-03-29 13:28:45 +02:00
|
|
|
|
|
|
|
/* Mark the slots in regs_ever_live for the hard regs
|
|
|
|
used by pseudo-reg number REGNO. */
|
|
|
|
extern void mark_home_live PROTO((int));
|
|
|
|
|
|
|
|
/* Scan X and replace any eliminable registers (such as fp) with a
|
|
|
|
replacement (such as sp), plus an offset. */
|
reload.h, [...]: Revert March 15 change.
* reload.h, reload1.c (eliminate_regs), caller-save.c, dbxout.c,
dwarfout.c, dwarf2out.c, reload.c, sdbout.c: Revert March 15 change.
* reload.c (push_reload): If WORD_REGISTER_OPERATIONS, reload the
SUBREG_REG if the word count is unchanged.
* reload1.c (eliminate_regs) [case SET]: If W_R_O, preserve
subregs of identical word size for push_reload.
From-SVN: r17105
1997-12-15 18:55:58 +01:00
|
|
|
extern rtx eliminate_regs PROTO((rtx, enum machine_mode, rtx));
|
1993-03-29 13:28:45 +02:00
|
|
|
|
1994-10-17 16:30:49 +01:00
|
|
|
/* Emit code to perform a reload from IN (which may be a reload register) to
|
|
|
|
OUT (which may also be a reload register). IN or OUT is from operand
|
|
|
|
OPNUM with reload type TYPE. */
|
|
|
|
extern rtx gen_reload PROTO((rtx, rtx, int, enum reload_type));
|
1993-03-29 13:28:45 +02:00
|
|
|
|
Fix consistency problems with reg_equiv_{mem,address};
Improve reload inheritance;
* reload.c (reload_out_reg): New variable.
(loc_mentioned_in_p, remove_address_replacements): New functions.
(remove_replacements): Deleted.
(push_reload): Set reload_out_reg[i].
When merging, also set reload_{in,out}_reg[i], and remove
duplicate address reloads.
(combine_reloads): Copy reload_out_reg[i].
(find_reloads): Do make_memloc substitution also when
reg_equiv_memory_loc[regno] and num_not_at_initial_offset
are both nonzero.
Include *recog_operand_loc in commutativity operand changes.
Generate optional output reloads.
Delete reference to n_memlocs. Don't set *recog_operand_loc before
processing operands. Call make_memloc in reg_equiv_address code.
Set *recog_operand_loc only after processing operands, and only
if replace is true. Return a value.
When changing address reload types for operands that didn't get
reloaded, use RELOAD_FOR_OPADDR_ADDRESS for
RELOAD_FOR_INPADDR_ADDRESS / RELOAD_FOR_OUTADDR_ADDRESS reloads.
Don't emit USEs for pseudo SUBREGs when not replacing.
(find_reloads_address): Do make_memloc substitution also when
reg_equiv_memory_loc[regno] and num_not_at_initial_offset
are both nonzero.
(find_reloads_toplev): Likewise.
Call make_memloc in reg_equiv_address code.
(debug_reload_to_stream): Add code to output reload_out_reg.
(make_memloc): Delete local variable i, ifdefed out code, and
references to memlocs and n_memlocs.
(memlocs, n_memlocs): Delete.
(push_secondary_reload): Clear reload_out_reg.
(find_reloads_address_1): Provide memrefloc argument to all calls
to find_reloads_address.
In AUTO_INC code, handle non-directly addressable equivalences properly.
* reload.h (reload_out_reg, num_not_at_initial_offset): Declare.
(find_reloads): Add return type.
(remove_address_replacements, deallocate_reload_reg): Declare.
* reload1.c (num_not_at_initial_offset): No longer static.
(delete_address_reloads, delete_address_reloads_1): Likewise.
(deallocate_reload_reg): New function.
(spill_reg_stored_to): New array.
(eliminate_regs): Don't substitute from reg_equiv_memory_loc.
(eliminate_regs_in_insn): Move assignments of previous_offset and
max_offset fields, and recalculation of num_not_at_initial_offset
into new static function:
(update_eliminable_offsets) .
(reload_as_needed): Call update_eliminable_offsetss after calling
find_reloads.
Call forget_old_reloads_1 with contents of reloaded auto_inc
expressions if the actual addressing can't be changed to match the
auto_inc.
(choose_reload_regs): For inheritance, replace
reload_reg_free_before_p test with reload_reg_ions.
(emit_reload_insns): If reload_in is a MEM, set OLD to
reload_in_reg[j].
Don't reload directly from oldequiv; if it's a pseudo with a
stack slot, use reload_in[j].
Check that reload_in_reg[j] is a MEM before replacing reload_in
from reg_reloaded_contents.
Include non-spill registers in reload inheritance processing.
Also try to use reload_out_reg to set spill_reg_store /
reg_last_reload_reg.
In code to set new_spill_reg_store, use single_set to find out if
there is a single set.
Add code that allows to delete optional output reloads.
Add code to allow deletion of output reloads that use no spill reg.
At the end, set reload_override_in to oldequiv.
Also call delete_output_reload if reload_out_reg is equal to old
in oldequiv code.
Add code to call delete_output_reload for stores with no matching load.
Set / use spill_reg_stored_to.
Handle case where secondary output reload uses a temporary, but
actual store isn't found.
When looking for a store of a value not loaded in order to call
delete_output_reload, count_occurences should return 0 for no
loads; but discount inherited input reloadill_reg_stored_to.
Do checks for extra uses of REG. Changed all
callers.
Use delete_address_reloads.
(reload): Take return value of find_reloads into account.
If a no-op set needs more than one reload, delete it.
(reload_reg_free_before_p): RELOAD_FOR_INPUT
can ignore RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS
for the same operand.
(clear_reload_reg_in_use): Check for other reloads that keep a
register in use.
(reload_reg_free_for_value_p): handle RELOAD_FOR_OPERAND_ADDRESS /
RELOAD_FOR_OPADDR_ADDR.
Take into account when an address address reload is only needed
for the address reload we are considering.
(count_occurrences): Use rtx_equal_p for MEMs.
(inc_for_reload): Return instruction that stores into RELOADREG.
New argument two, IN, and rtx. Changed all callers.
(calculate_needs_all_insns, reload_as_needed):
Don't clear after_call for a CLOBBER.
Keep track of how many hard registers need to be copied from
after_call, and don't clear after_call before we have seen
that much copies, or we see a different instruction.
From-SVN: r23143
1998-10-16 21:54:38 +02:00
|
|
|
/* Deallocate the reload register used by reload number R. */
|
|
|
|
extern void deallocate_reload_reg PROTO((int r));
|
|
|
|
|
1993-03-29 13:28:45 +02:00
|
|
|
/* Functions in caller-save.c: */
|
|
|
|
|
|
|
|
/* Initialize for caller-save. */
|
|
|
|
extern void init_caller_save PROTO((void));
|
|
|
|
|
|
|
|
/* Initialize save areas by showing that we haven't allocated any yet. */
|
|
|
|
extern void init_save_areas PROTO((void));
|
|
|
|
|
|
|
|
/* Allocate save areas for any hard registers that might need saving. */
|
1998-10-07 02:13:49 +02:00
|
|
|
extern void setup_save_areas PROTO((void));
|
1993-03-29 13:28:45 +02:00
|
|
|
|
|
|
|
/* Find the places where hard regs are live across calls and save them. */
|
1998-10-07 02:13:49 +02:00
|
|
|
extern void save_call_clobbered_regs PROTO((void));
|