gcc/gcc/reload.h

341 lines
13 KiB
C
Raw Normal View History

1991-09-30 02:34:16 +01:00
/* Communication between reload.c and reload1.c.
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
/* 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
/* 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))
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];
extern char reload_nongroup[MAX_RELOADS];
1991-09-30 02:34:16 +01:00
extern int reload_inc[MAX_RELOADS];
extern int reload_opnum[MAX_RELOADS];
1991-09-30 02:34:16 +01:00
extern int reload_secondary_p[MAX_RELOADS];
extern int reload_secondary_in_reload[MAX_RELOADS];
extern int reload_secondary_out_reload[MAX_RELOADS];
#ifdef MAX_INSN_CODE
extern enum insn_code reload_secondary_in_icode[MAX_RELOADS];
extern enum insn_code reload_secondary_out_icode[MAX_RELOADS];
#endif
1991-09-30 02:34:16 +01:00
extern int n_reloads;
extern rtx reload_reg_rtx[MAX_RELOADS];
/* 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
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
RELOAD_FOR_OPERAND_ADDRESS reload for the address of a non-reloaded
operand; these don't conflict with
any other addresses.
RELOAD_FOR_OPADDR_ADDR reload needed for RELOAD_FOR_OPERAND_ADDRESS
reloads; usually secondary reloads
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
{
RELOAD_FOR_INPUT, RELOAD_FOR_OUTPUT, RELOAD_FOR_INSN,
RELOAD_FOR_INPUT_ADDRESS, RELOAD_FOR_INPADDR_ADDRESS,
RELOAD_FOR_OUTPUT_ADDRESS, RELOAD_FOR_OUTADDR_ADDRESS,
RELOAD_FOR_OPERAND_ADDRESS, RELOAD_FOR_OPADDR_ADDR,
RELOAD_OTHER, RELOAD_FOR_OTHER_ADDRESS
1991-09-30 02:34:16 +01:00
};
extern enum reload_type reload_when_needed[MAX_RELOADS];
1991-09-30 02:34:16 +01:00
extern rtx *reg_equiv_constant;
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];
/* 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;
#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));
reload.h (compute_use_by_pseudos): Declare. * reload.h (compute_use_by_pseudos): Declare. * reload1.c (spilled_pseudos, insns_need_reload): New variables. (something_needs_reloads): Delete variable. (finish_spills): New function. (compute_use_by_pseudos): New function. (delete_caller_save_insns): Lose argument FIRST. All callers changed. Use the reload_insn_chain instead of walking the rtl directly. (reload): Allocate and free spilled_pseudos. Ensure that all calls of spill_hard_reg are followed by a call to finish_spills. Use the insns_need_reload list instead of something_needs_reloads to find out if reload_as_needed must be called. Clear unused_insn_chains at the end. (calculate_needs_all_insns): Lose FIRST parameter. All callers changed. Delete code to keep track of current basic block. Walk reload_insn_chain instead of the rtl structure. Build the insns_need_reload chain. Remember which insns need reloading/elimination by setting the appropriate fields in struct insn_chain, not by putting modes on the insn. (calculate_needs): Lose THIS_BLOCK arg. Accept arg CHAIN instead of arg INSN. All callers changed. Delete declaration of struct needs. Don't set something_needs_reloads. Record insn needs in the CHAIN argument. (spill_hard_reg): Record the affected pseudos in spilled_pseudos. (reload_as_needed): Lose FIRST arg. All callers changed. Walk the reload_insn_chain instead of the rtx structure. Delete code to keep track of current basic block. Rename one of the NEXT variables to OLD_NEXT. (allocate_reload_reg): Accept arg CHAIN instead of arg INSN. All callers changed. (choose_reload_regs): Likewise. (emit_reload_insns): Replace INSN and BB args with arg CHAIN. All callers changed. * caller-save.c (MOVE_MAX_WORDS): New macro. Use it throughout instead of (MOVE_MAX / UNITS_PER_WORD) computation. (hard_regs_live, hard_regs_need_restore): Delete variables. (n_regs_saved): Now static. (referenced_regs, this_insn_sets): New variables. (setup_save_areas): Restructure the code a bit. (restore_referenced_regs): Delete function. (mark_referenced_regs): New function, similar to the old restore_referenced_regs, but mark registers in referenced_regs. (clear_reg_live): Delete function. (mark_set_regs): Renamed from set_reg_live. All callers changed. Only mark registers in this_insn_sets. (save_call_clobbered_regs): Rework this function to walk the reload_insn_chain instead of using the list of instructions directly. Delete code to keep track of register lives, compute live regs on the fly from information in the chain. Instead of calling restore_referenced_regs, use mark_referenced_regs, then walk the set it computes and call insert_restore as appropriate. (insert_restore): Lose INSN and BLOCK args. Add CHAIN arg. All callers changed. Restructure the code a bit. Test hard_regs_saved instead of hard_regs_need_restore. (insert_save): Lose INSN and BLOCK args. Add CHAIN and TO_SAVE args. All callers changed. Restructure the code a bit. Use TO_SAVE to determine which regs to save instead of more complicated test. (insert_one_arg): Lose INSN and BLOCK args. Add CHAIN arg. All callers changed. Create a new insn_chain structure for the new insn and place it into the chain. * rtl.texi: Update documentation to reflect that reload no longer puts modes on the insns. From-SVN: r23074
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
/* 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));
/* 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
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 *));
/* 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));
/* 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));
/* Change any replacements being done to *X to be done to *Y */
extern void move_replacements PROTO((rtx *x, rtx *y));
/* 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 *));
/* 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));
int count_occurrences PROTO((rtx, rtx));
/* Initialize the reload pass once per compilation. */
extern void init_reload PROTO((void));
/* The reload pass itself. */
extern int reload PROTO((rtx, int, FILE *));
/* 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. */
extern rtx eliminate_regs PROTO((rtx, enum machine_mode, rtx));
/* 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));
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));
/* 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. */
extern void setup_save_areas PROTO((void));
/* Find the places where hard regs are live across calls and save them. */
extern void save_call_clobbered_regs PROTO((void));