GCC Middle and Back End API Reference
reload.c File Reference

Data Structures

struct  replacement
struct  decomposition

Functions

static bool small_register_class_p ()
static int push_secondary_reload (int, rtx, int, int, enum reg_class, enum machine_mode, enum reload_type, enum insn_code *, secondary_reload_info *)
static enum reg_class find_valid_class (enum machine_mode, enum machine_mode, int, unsigned int)
static void push_replacement (rtx *, int, enum machine_mode)
static void dup_replacements (rtx *, rtx *)
static void combine_reloads (void)
static int find_reusable_reload (rtx *, rtx, enum reg_class, enum reload_type, int, int)
static rtx find_dummy_reload (rtx, rtx, rtx *, rtx *, enum machine_mode, enum machine_mode, reg_class_t, int, int)
static int hard_reg_set_here_p (unsigned int, unsigned int, rtx)
static struct decomposition decompose (rtx)
static int immune_p (rtx, rtx, struct decomposition)
static bool alternative_allows_const_pool_ref (rtx, const char *, int)
static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int, rtx, int *)
static rtx make_memloc (rtx, int)
static int maybe_memory_address_addr_space_p (enum machine_mode, rtx, addr_space_t, rtx *)
static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *, int, enum reload_type, int, rtx)
static rtx subst_reg_equivs (rtx, rtx)
static rtx subst_indexed_address (rtx)
static void update_auto_inc_notes (rtx, int, int)
static int find_reloads_address_1 (enum machine_mode, addr_space_t, rtx, int, enum rtx_code, enum rtx_code, rtx *, int, enum reload_type, int, rtx)
static void find_reloads_address_part (rtx, rtx *, enum reg_class, enum machine_mode, int, enum reload_type, int)
static rtx find_reloads_subreg_address (rtx, int, enum reload_type, int, rtx, int *)
static void copy_replacements_1 (rtx *, rtx *, int)
static int find_inc_amount (rtx, rtx)
static int refers_to_mem_for_reload_p (rtx)
static int refers_to_regno_for_reload_p (unsigned int, unsigned int, rtx, rtx *)
static void push_reg_equiv_alt_mem ()
reg_class_t secondary_reload_class (bool in_p, reg_class_t rclass, enum machine_mode mode, rtx x)
enum reg_class scratch_reload_class ()
rtx get_secondary_mem (rtx x, enum machine_mode mode, int opnum, enum reload_type type)
void clear_secondary_mem ()
static enum reg_class find_valid_class_1 (enum machine_mode outer, enum machine_mode mode, enum reg_class dest_class)
static bool reload_inner_reg_of_subreg ()
static int can_reload_into ()
int push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, enum reg_class rclass, enum machine_mode inmode, enum machine_mode outmode, int strict_low, int optional, int opnum, enum reload_type type)
static void push_replacement ()
static void dup_replacements ()
void transfer_replacements ()
int remove_address_replacements ()
int earlyclobber_operand_p ()
static int hard_reg_set_here_p ()
int strict_memory_address_addr_space_p (enum machine_mode mode, rtx addr, addr_space_t as)
int operands_match_p ()
static struct decomposition decompose ()
static int immune_p ()
int safe_from_earlyclobber ()
int find_reloads (rtx insn, int replace, int ind_levels, int live_known, short *reload_reg_p)
static rtx make_memloc ()
static rtx subst_reg_equivs ()
rtx form_sum ()
static rtx subst_indexed_address ()
void subst_reloads ()
void copy_replacements ()
static void copy_replacements_1 ()
void move_replacements ()
rtx find_replacement ()
int reg_overlap_mentioned_for_reload_p ()
static int refers_to_mem_for_reload_p ()
rtx find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other, short *reload_reg_p, int goalreg, enum machine_mode mode)
static int find_inc_amount ()
static int reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno, rtx insn)
int regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode, int sets)
rtx reload_adjust_reg_for_mode ()
DEBUG_FUNCTION void debug_reload_to_stream ()
DEBUG_FUNCTION void debug_reload ()

Variables

int n_reloads
struct reload rld [MAX_RELOADS]
int n_earlyclobbers
rtx reload_earlyclobbers [MAX_RECOG_OPERANDS]
int reload_n_operands
static int replace_reloads
static struct replacement replacements [MAX_RECOG_OPERANDS *((MAX_REGS_PER_ADDRESS *2)+1)]
static int n_replacements
static rtx secondary_memlocs [NUM_MACHINE_MODES]
static rtx secondary_memlocs_elim [NUM_MACHINE_MODES][MAX_RECOG_OPERANDS]
static int secondary_memlocs_elim_used = 0
static rtx this_insn
static int this_insn_is_asm
static int hard_regs_live_known
static short * static_reload_reg_p
static int subst_reg_equivs_changed
static int output_reloadnum
static const char *const reload_when_needed_name []

Function Documentation

static bool alternative_allows_const_pool_ref ( rtx  mem,
const char *  constraint,
int  altnum 
)
static
Return true if alternative number ALTNUM in constraint-string
   CONSTRAINT is guaranteed to accept a reloaded constant-pool reference.
   MEM gives the reference if it didn't need any reloads, otherwise it
   is null.   

Referenced by find_reloads().

static int can_reload_into ( )
static
Return nonzero if IN can be reloaded into REGNO with mode MODE without
   requiring an extra reload register.  The caller has already found that
   IN contains some reference to REGNO, so check that we can produce the
   new value in a single step.  E.g. if we have
   (set (reg r13) (plus (reg r13) (const int 1))), and there is an
   instruction that adds one to a register, this should succeed.
   However, if we have something like
   (set (reg r13) (plus (reg r13) (const int 999))), and the constant 999
   needs to be loaded into a register first, we need a separate reload
   register.
   Such PLUS reloads are generated by find_reload_address_part.
   The out-of-range PLUS expressions are usually introduced in the instruction
   patterns by register elimination and substituting pseudos without a home
   by their function-invariant equivalences.   

References constrain_operands(), extract_insn(), gen_rtx_REG(), make_insn_raw(), recog_data, recog_memoized(), and test_insn.

Referenced by push_reload().

void clear_secondary_mem ( void  )
Clear any secondary memory locations we've made.   

References memset(), and secondary_memlocs.

Referenced by reload().

static void combine_reloads ( )
static
If there is only one output reload, and it is not for an earlyclobber
   operand, try to combine it with a (logically unrelated) input reload
   to reduce the number of reload registers needed.

   This is safe if the input reload does not appear in
   the value being output-reloaded, because this implies
   it is not needed any more once the original insn completes.

   If that doesn't work, see we can use any of the registers that
   die in this insn as a reload register.  We can if it is of the right
   class and does not appear in the value being output-reloaded.   

References bitmap_bit_p(), insn_operand_data::constraint, earlyclobber_operand_p(), gen_rtx_REG(), insn_data, insn_data_d::n_operands, n_reloads, n_replacements, insn_data_d::operand, reload::opnum, reload::out, reload::out_reg, reload::outmode, reload::rclass, reg_class_subset_p(), reg_overlap_mentioned_for_reload_p(), RELOAD_FOR_INPUT, RELOAD_FOR_OUTADDR_ADDRESS, RELOAD_FOR_OUTPUT, RELOAD_FOR_OUTPUT_ADDRESS, reload_inner_reg_of_subreg(), RELOAD_OTHER, replacements, rld, rtx_equal_p(), secondary_memlocs_elim, reload::secondary_out_icode, reload::secondary_out_reload, targetm, this_insn, replacement::what, and reload::when_needed.

Referenced by find_reloads().

void copy_replacements ( )
Make a copy of any replacements being done into X and move those
   copies to locations in Y, a copy of X.   

References copy_replacements_1(), and n_replacements.

Referenced by emit_move_change_mode(), and find_reloads_address().

static void copy_replacements_1 ( rtx ,
rtx ,
int   
)
static
static void copy_replacements_1 ( )
static
DEBUG_FUNCTION void debug_reload ( void  )
DEBUG_FUNCTION void debug_reload_to_stream ( )
These functions are used to print the variables set by 'find_reloads'  

References insn_data, n_reloads, print_inline_rtx(), reg_class_names, reload_when_needed_name, and rld.

Referenced by debug_reload(), emit_reload_insns(), and spill_failure().

static struct decomposition decompose ( rtx  )
staticread
static struct decomposition decompose ( )
staticread
Describe the range of registers or memory referenced by X.
   If X is a register, set REG_FLAG and put the first register
   number into START and the last plus one into END.
   If X is a memory reference, put a base address into BASE
   and a range of integer offsets into START and END.
   If X is pushing on the stack, we can assume it causes no trouble,
   so we set the SAFE field.   

References decomposition::base, decompose(), decomposition::end, end_hard_regno(), memset(), offset, decomposition::reg_flag, decomposition::safe, decomposition::start, subreg_nregs(), and true_regnum().

static void dup_replacements ( rtx ,
rtx  
)
static

Referenced by find_reloads().

static void dup_replacements ( )
static
Duplicate any replacement we have recorded to apply at
   location ORIG_LOC to also be performed at DUP_LOC.
   This is used in insn patterns that use match_dup.   

References replacement::mode, n_replacements, push_replacement(), replacements, replacement::what, and replacement::where.

int earlyclobber_operand_p ( )
This page contains subroutines used mainly for determining
   whether the IN or an OUT of a reload can serve as the
   reload register.   
Return 1 if X is an operand of an insn that is being earlyclobbered.   

References n_earlyclobbers, and reload_earlyclobbers.

Referenced by combine_reloads(), find_reusable_reload(), push_reload(), refers_to_regno_for_reload_p(), and reload_reg_free_for_value_p().

static rtx find_dummy_reload ( rtx  real_in,
rtx  real_out,
rtx inloc,
rtx outloc,
enum machine_mode  inmode,
enum machine_mode  outmode,
reg_class_t  rclass,
int  for_real,
int  earlyclobber 
)
static
Try to find a reload register for an in-out reload (expressions IN and OUT).
   See if one of IN and OUT is a register that may be used;
   this is desirable since a spill-register won't be needed.
   If so, return the register rtx that proves acceptable.

   INLOC and OUTLOC are locations where IN and OUT appear in the insn.
   RCLASS is the register class required for the reload.

   If FOR_REAL is >= 0, it is the number of the reload,
   and in some cases when it can be discovered that OUT doesn't need
   to be computed, clear out rld[FOR_REAL].out.

   If FOR_REAL is -1, this should not be done, because this call
   is just to see if a register can be found, not to find and install it.

   EARLYCLOBBER is nonzero if OUT is an earlyclobber operand.  This
   puts an additional constraint on being able to use IN for OUT since
   IN must not appear elsewhere in the insn (it is assumed that IN itself
   is safe from the earlyclobber).   

References bitmap_bit_p(), find_reg_note(), gen_rtx_REG(), hard_reg_set_here_p(), hard_regs_live_known, reload::out, refers_to_regno_for_reload_p(), rld, subreg_regno_offset(), targetm, and this_insn.

Referenced by find_reloads(), and push_reload().

rtx find_equiv_reg ( rtx  goal,
rtx  insn,
enum reg_class  rclass,
int  other,
short *  reload_reg_p,
int  goalreg,
enum machine_mode  mode 
)
Check the insns before INSN to see if there is a suitable register
   containing the same value as GOAL.
   If OTHER is -1, look for a register in class RCLASS.
   Otherwise, just see if register number OTHER shares GOAL's value.

   Return an rtx for the register found, or zero if none is found.

   If RELOAD_REG_P is (short *)1,
   we reject any hard reg that appears in reload_reg_rtx
   because such a hard reg is also needed coming into this insn.

   If RELOAD_REG_P is any other nonzero value,
   it is a vector indexed by hard reg number
   and we reject any hard reg whose element in the vector is nonnegative
   as well as any that appears in reload_reg_rtx.

   If GOAL is zero, then GOALREG is a register number; we look
   for an equivalent for that register.

   MODE is the machine mode of the value we want an equivalence for.
   If GOAL is nonzero and not VOIDmode, then it must have mode MODE.

   This function is used by jump.c as well as in the reload pass.

   If GOAL is the sum of the stack pointer and a constant, we treat it
   as if it were a constant except that sp is required to be unchanging.   

References end_hard_regno(), find_reg_note(), HOST_WIDE_INT, in_hard_reg_set_p(), replacement::mode, n_reloads, operand_subword(), push_operand(), refers_to_regno_for_reload_p(), reg_overlap_mentioned_for_reload_p(), reload_first_uid, rld, rtx_equal_p(), rtx_renumbered_equal_p(), SET, true_regnum(), volatile_insn_p(), and replacement::where.

Referenced by choose_reload_regs(), find_reloads(), and push_reload().

static int find_inc_amount ( rtx  ,
rtx   
)
static
static int find_inc_amount ( )
static
Find a place where INCED appears in an increment or decrement operator
   within X, and return the amount INCED is incremented or decremented by.
   The value is always positive.   

References find_inc_amount().

int find_reloads ( rtx  insn,
int  replace,
int  ind_levels,
int  live_known,
short *  reload_reg_p 
)
Main entry point of this file: 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.

   IND_LEVELS says how many levels of indirection are supported by this
   machine; a value of zero means that a memory reference is not a valid
   memory address.

   LIVE_KNOWN says we have valid information about which hard
   regs are live at each point in the program; this is true when
   we are called from global_alloc but false when stupid register
   allocation has been done.

   RELOAD_REG_P if nonzero is a vector indexed by hard reg number
   which is nonnegative if the reg has been commandeered for reloading into.
   It is copied into STATIC_RELOAD_REG_P and referenced from there
   by various subroutines.

   Return TRUE if some operands need to be changed, because of swapping
   commutative operands, reg_equiv_address substitution, or whatever.   

References add_reg_note(), alternative_allows_const_pool_ref(), recog_data_d::alternative_enabled_p, base_reg_class(), cc0_rtx, combine_reloads(), recog_data_d::constraints, constraints, decompose(), recog_data_d::dup_loc, recog_data_d::dup_num, dup_replacements(), elimination_target_reg_p(), emit_insn_after(), emit_insn_before(), decomposition::end, error_for_asm(), extract_insn(), find_dummy_reload(), find_equiv_reg(), find_reg_note(), find_reloads(), find_reloads_address(), find_reloads_toplev(), force_const_mem(), gen_clobber(), gen_rtx_SUBREG(), get_address_mode(), hard_regs_live_known, immune_p(), reload::in, reload::in_reg, reload::inc, reload::inmode, insn_code_number, insn_data, recog_data_d::is_operator, label_is_jump_target_p(), len, memcpy(), memset(), reload::mode, n_alternatives(), recog_data_d::n_alternatives, recog_data_d::n_dups, n_earlyclobbers, recog_data_d::n_operands, n_reloads, n_replacements, nr, reload::nregs, num_not_at_initial_offset, offset, offsettable_memref_p(), offsettable_nonstrict_memref_p(), recog_data_d::operand, insn_data_d::operand, recog_data_d::operand_loc, recog_data_d::operand_mode, operands_match_p(), reload::opnum, reload::outmode, output_reloadnum, push_reload(), reload::rclass, recog_data, reg_alternate_class(), reg_class_subset_p(), reg_fits_class_p(), reg_mentioned_p(), reg_preferred_class(), reg_referenced_p(), reg_renumber, reload::reg_rtx, reg_set_p(), register_move_cost(), reject(), reload_earlyclobbers, RELOAD_FOR_INPADDR_ADDRESS, RELOAD_FOR_INPUT, RELOAD_FOR_INPUT_ADDRESS, RELOAD_FOR_INSN, RELOAD_FOR_OPADDR_ADDR, RELOAD_FOR_OPERAND_ADDRESS, RELOAD_FOR_OTHER_ADDRESS, RELOAD_FOR_OUTADDR_ADDRESS, RELOAD_FOR_OUTPUT, RELOAD_FOR_OUTPUT_ADDRESS, reload_n_operands, RELOAD_OTHER, replace_reloads, replacements, rld, rtx_equal_p(), RTX_UNARY, secondary_memlocs_elim, secondary_memlocs_elim_used, SET, set_unique_reg_note(), simplify_subreg_regno(), skip_alternative(), small_register_class_p(), static_reload_reg_p, insn_operand_data::strict_low, subreg_regno_offset(), targetm, this_insn, this_insn_is_asm, transfer_replacements(), type(), replacement::what, and reload::when_needed.

Referenced by calculate_needs_all_insns(), find_reloads(), and reload_as_needed().

static int find_reloads_address ( enum machine_mode  mode,
rtx memrefloc,
rtx  ad,
rtx loc,
int  opnum,
enum reload_type  type,
int  ind_levels,
rtx  insn 
)
static
Record all reloads needed for handling memory address AD
   which appears in *LOC in a memory reference to mode MODE
   which itself is found in location  *MEMREFLOC.
   Note that we take shortcuts assuming that no multi-reg machine mode
   occurs as part of an address.

   OPNUM and TYPE specify the purpose of this reload.

   IND_LEVELS says how many levels of indirect addressing this machine
   supports.

   INSN, if nonzero, is the insn in which we do the reload.  It is used
   to determine if we may generate output reloads, and where to put USEs
   for pseudos that we have to replace with stack slots.

   Value is one if this address is reloaded or replaced as a whole; it is
   zero if the top level of this address was not reloaded or replaced, and
   it is -1 if it may or may not have been reloaded or replaced.

   Note that there is no verification that the address will be valid after
   this routine does its work.  Instead, we rely on the fact that the address
   was valid when reload started.  So we need only undo things that reload
   could have broken.  These are wrong register types, pseudos not allocated
   to a hard register, and frame pointer elimination.   

References base_reg_class(), copy_replacements(), copy_rtx(), emit_insn_before(), find_reloads_address_1(), find_reloads_address_part(), make_memloc(), maybe_memory_address_addr_space_p(), move_replacements(), num_not_at_initial_offset, plus_constant(), push_reg_equiv_alt_mem(), push_reload(), regno_clobbered_p(), regno_ok_for_base_p(), replace_reloads, rtx_equal_p(), strict_memory_address_addr_space_p(), subst_indexed_address(), subst_reg_equivs(), subst_reg_equivs_changed, targetm, and this_insn.

Referenced by find_reloads(), find_reloads_address_1(), find_reloads_address_part(), find_reloads_subreg_address(), find_reloads_toplev(), and get_secondary_mem().

static int find_reloads_address_1 ( enum machine_mode  mode,
addr_space_t  as,
rtx  x,
int  context,
enum rtx_code  outer_code,
enum rtx_code  index_code,
rtx loc,
int  opnum,
enum reload_type  type,
int  ind_levels,
rtx  insn 
)
static
Record the pseudo registers we must reload into hard registers in a
   subexpression of a would-be memory address, X referring to a value
   in mode MODE.  (This function is not called if the address we find
   is strictly valid.)

   CONTEXT = 1 means we are considering regs as index regs,
   = 0 means we are considering them as base regs.
   OUTER_CODE is the code of the enclosing RTX, typically a MEM, a PLUS,
   or an autoinc code.
   If CONTEXT == 0 and OUTER_CODE is a PLUS or LO_SUM, then INDEX_CODE
   is the code of the index part of the address.  Otherwise, pass SCRATCH
   for this argument.
   OPNUM and TYPE specify the purpose of any reloads made.

   IND_LEVELS says how many levels of indirect addressing are
   supported at this point in the address.

   INSN, if nonzero, is the insn in which we do the reload.  It is used
   to determine if we may generate output reloads.

   We return nonzero if X, as a whole, is reloaded or replaced.   
Note that we take shortcuts assuming that no multi-reg machine mode
   occurs as part of an address.
   Also, this is not fully machine-customizable; it works for machines
   such as VAXen and 68000's and 32000's, but other possible machines
   could have addressing modes that this does not handle right.
   If you add push_reload calls here, you need to make sure gen_reload
   handles those cases gracefully.   

References base_reg_class(), find_inc_amount(), find_reloads_address(), find_reloads_address_part(), find_reloads_subreg_address(), gen_rtx_REG(), reload::inc, insn_operand_matches(), make_memloc(), memory_operand(), num_not_at_initial_offset, optab_handler(), push_reg_equiv_alt_mem(), push_reload(), reg_renumber, regno_clobbered_p(), regno_ok_for_base_p(), RELOAD_OTHER, rld, rtx_equal_p(), sets_cc0_p(), subreg_regno(), subreg_regno_offset(), this_insn, update_auto_inc_notes(), and word_mode.

Referenced by find_reloads_address().

static void find_reloads_address_part ( rtx  x,
rtx loc,
enum reg_class  rclass,
enum machine_mode  mode,
int  opnum,
enum reload_type  type,
int  ind_levels 
)
static
X, which is found at *LOC, is a part of an address that needs to be
   reloaded into a register of class RCLASS.  If X is a constant, or if
   X is a PLUS that contains a constant, check that the constant is a
   legitimate operand and that we are supposed to be able to load
   it into the register.

   If not, force the constant into memory and reload the MEM instead.

   MODE is the mode to use, in case X is an integer constant.

   OPNUM and TYPE describe the purpose of any reloads made.

   IND_LEVELS says how many levels of indirect addressing this machine
   supports.   

References find_reloads_address(), force_const_mem(), push_reload(), and targetm.

Referenced by find_reloads_address(), and find_reloads_address_1().

static rtx find_reloads_subreg_address ( rtx  x,
int  opnum,
enum reload_type  type,
int  ind_levels,
rtx  insn,
int *  address_reloaded 
)
static
X, a subreg of a pseudo, is a part of an address that needs to be
   reloaded, and the pseusdo is equivalent to a memory location.

   Attempt to replace the whole subreg by a (possibly narrower or wider)
   memory reference.  If this is possible, return this new memory
   reference, and push all required address reloads.  Otherwise,
   return NULL.

   OPNUM and TYPE identify the purpose of the reload.

   IND_LEVELS says how many levels of indirect addressing are
   supported at this point in the address.

   INSN, if nonzero, is the insn in which we do the reload.  It is used
   to determine where to put USEs for pseudos that we have to replace with
   stack slots.   

References base_reg_class(), emit_insn_before(), find_reloads_address(), make_memloc(), offset, recog_data_d::operand, paradoxical_subreg_p(), push_reg_equiv_alt_mem(), push_reload(), recog_data, replace_reloads, rtx_equal_p(), simplify_subreg(), and strict_memory_address_addr_space_p().

Referenced by find_reloads_address_1(), and find_reloads_toplev().

static rtx find_reloads_toplev ( rtx  x,
int  opnum,
enum reload_type  type,
int  ind_levels,
int  is_set_dest,
rtx  insn,
int *  address_reloaded 
)
static
Scan X for memory references and scan the addresses for reloading.
   Also checks for references to "constant" regs that we want to eliminate
   and replaces them with the values they stand for.
   We may alter X destructively if it contains a reference to such.
   If X is just a constant reg, we return the equivalent value
   instead of X.

   IND_LEVELS says how many levels of indirect addressing this machine
   supports.

   OPNUM and TYPE identify the purpose of the reload.

   IS_SET_DEST is true if X is the destination of a SET, which is not
   appropriate to be replaced by a constant.

   INSN, if nonzero, is the insn in which we do the reload.  It is used
   to determine if we may generate output reloads, and where to put USEs
   for pseudos that we have to replace with stack slots.

   ADDRESS_RELOADED.  If nonzero, is a pointer to where we put the
   result of find_reloads_address.   

References emit_insn_before(), find_reloads_address(), find_reloads_subreg_address(), force_const_mem(), make_memloc(), num_not_at_initial_offset, recog_data_d::operand, push_reg_equiv_alt_mem(), recog_data, reg_renumber, replace_reloads, rtx_equal_p(), simplify_gen_subreg(), and targetm.

Referenced by find_reloads().

rtx find_replacement ( )
If LOC was scheduled to be replaced by something, return the replacement.
   Otherwise, return *LOC.   

References replacement::mode, n_replacements, reload::reg_rtx, reload_adjust_reg_for_mode(), replacements, rld, simplify_gen_subreg(), replacement::what, and replacement::where.

Referenced by emit_move_multi_word(), gen_reload(), inc_for_reload(), and replaced_subreg().

static int find_reusable_reload ( rtx p_in,
rtx  out,
enum reg_class  rclass,
enum reload_type  type,
int  opnum,
int  dont_share 
)
static
Return the number of a previously made reload that can be combined with
   a new one, or n_reloads if none of the existing reloads can be used.
   OUT, RCLASS, TYPE and OPNUM are the same arguments as passed to
   push_reload, they determine the kind of the new reload that we try to
   combine.  P_IN points to the corresponding value of IN, which can be
   modified by this function.
   DONT_SHARE is nonzero if we can't share any input-only reload for IN.   

References earlyclobber_operand_p(), n_reloads, reload::out, reg_class_subset_p(), rld, RTX_AUTOINC, small_register_class_p(), targetm, and true_regnum().

Referenced by push_reload().

static enum reg_class find_valid_class ( enum machine_mode  outer,
enum machine_mode  inner,
int  n,
unsigned int  dest_regno 
)
static
Find the largest class which has at least one register valid in
   mode INNER, and which for every such register, that register number
   plus N is also valid in OUTER (if in range) and is cheap to move
   into REGNO.  Such a class must exist.   

References register_move_cost().

Referenced by push_reload().

static enum reg_class find_valid_class_1 ( enum machine_mode  outer,
enum machine_mode  mode,
enum reg_class  dest_class 
)
static
We are trying to reload a subreg of something that is not a register.
   Find the largest class which contains only registers valid in
   mode MODE.  OUTER is the mode of the subreg, DEST_CLASS the class in
   which we would eventually like to obtain the object.   

References in_hard_reg_set_p(), and register_move_cost().

Referenced by push_reload().

rtx form_sum ( )
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.

   This routine assumes both inputs are already in canonical form.   

References form_sum(), and plus_constant().

rtx get_secondary_mem ( rtx  x,
enum machine_mode  mode,
int  opnum,
enum reload_type  type 
)
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.   

References assign_stack_local(), copy_rtx(), eliminate_regs(), find_reloads_address(), mode_for_size(), RELOAD_FOR_INPUT, RELOAD_FOR_INPUT_ADDRESS, RELOAD_FOR_OUTPUT, RELOAD_FOR_OUTPUT_ADDRESS, RELOAD_OTHER, secondary_memlocs, secondary_memlocs_elim, secondary_memlocs_elim_used, and strict_memory_address_addr_space_p().

Referenced by choose_reload_regs(), gen_reload(), push_reload(), and push_secondary_reload().

static int hard_reg_set_here_p ( unsigned  int,
unsigned  int,
rtx   
)
static
static int hard_reg_set_here_p ( )
static
Return 1 if expression X alters a hard reg in the range
   from BEG_REGNO (inclusive) to END_REGNO (exclusive),
   either explicitly or in the guise of a pseudo-reg allocated to REGNO.
   X should be the body of an instruction.   

References end_hard_regno(), hard_reg_set_here_p(), and SET.

static int immune_p ( rtx  ,
rtx  ,
struct decomposition   
)
static
static int immune_p ( )
static
Return 1 if altering Y will not modify the value of X.
   Y is also described by YDATA, which should be decompose (Y).   

References decomposition::base, decompose(), decomposition::end, refers_to_regno_for_reload_p(), decomposition::reg_flag, rtx_equal_p(), decomposition::safe, and decomposition::start.

static rtx make_memloc ( )
static
Return a mem ref for the memory equivalent of reg REGNO.
   This mem ref is not shared with anything.   

References copy_rtx(), eliminate_regs(), replace_equiv_address_nv(), and rtx_varies_p().

static int maybe_memory_address_addr_space_p ( enum machine_mode  mode,
rtx  ad,
addr_space_t  as,
rtx part 
)
static
Returns true if AD could be turned into a valid memory reference
   to mode MODE in address space AS by reloading the part pointed to
   by PART into a register.   

References gen_rtx_REG(), max_reg_num(), and memory_address_addr_space_p().

Referenced by find_reloads_address().

void move_replacements ( )
Change any replacements being done to *X to be done to *Y.   

References n_replacements, replacements, and replacement::where.

Referenced by find_reloads_address().

int operands_match_p ( )
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.
   This is specifically intended for find_reloads to use
   in determining whether two operands match.
   X is the operand whose number is the lower of the two.

   The value is 2 if Y contains a pre-increment that matches
   a non-incrementing address in X.   
??? To be completely correct, we should arrange to pass
   for X the output operand and for Y the input operand.
   For now, we assume that the output operand has the lower number
   because that is natural in (SET output (... input ...)).   

References operands_match_p(), and subreg_regno_offset().

static void push_reg_equiv_alt_mem ( )
static
Add NEW to reg_equiv_alt_mem_list[REGNO] if it's not present in the
   list yet.   

References alloc_EXPR_LIST(), and rtx_equal_p().

Referenced by find_reloads_address(), find_reloads_address_1(), find_reloads_subreg_address(), and find_reloads_toplev().

int push_reload ( rtx  in,
rtx  out,
rtx inloc,
rtx outloc,
enum reg_class  rclass,
enum machine_mode  inmode,
enum machine_mode  outmode,
int  strict_low,
int  optional,
int  opnum,
enum reload_type  type 
)
Record one reload that needs to be performed.
   IN is an rtx saying where the data are to be found before this instruction.
   OUT says where they must be stored after the instruction.
   (IN is zero for data not read, and OUT is zero for data not written.)
   INLOC and OUTLOC point to the places in the instructions where
   IN and OUT were found.
   If IN and OUT are both nonzero, it means the same register must be used
   to reload both IN and OUT.

   RCLASS is a register class required for the reloaded data.
   INMODE is the machine mode that the instruction requires
   for the reg that replaces IN and OUTMODE is likewise for OUT.

   If IN is zero, then OUT's location and mode should be passed as
   INLOC and INMODE.

   STRICT_LOW is the 1 if there is a containing STRICT_LOW_PART rtx.

   OPTIONAL nonzero means this reload does not need to be performed:
   it can be discarded if that is more convenient.

   OPNUM and TYPE say what the purpose of this reload is.

   The return value is the reload-number for this reload.

   If both IN and OUT are nonzero, in some rare cases we might
   want to make two separate reloads.  (Actually we never do this now.)
   Therefore, the reload-number for OUT is stored in
   output_reloadnum when we return; the return value applies to IN.
   Usually (presently always), when IN and OUT are nonzero,
   the two reload-numbers are equal, but the caller should be careful to
   distinguish them.   

References bitmap_bit_p(), can_reload_into(), earlyclobber_operand_p(), end_hard_regno(), error_for_asm(), find_dummy_reload(), find_equiv_reg(), find_inc_amount(), find_reusable_reload(), find_valid_class(), find_valid_class_1(), gen_rtx_REG(), get_secondary_mem(), hard_reg_set_here_p(), hard_regs_live_known, reload::in, in_hard_reg_set_p(), reload::in_reg, reload::inc, reload::inmode, replacement::mode, n_reloads, n_replacements, reload::nocombine, reload::opnum, reload::optional, reload::out, reload::out_reg, reload::outmode, output_reloadnum, push_reload(), push_secondary_reload(), reload::rclass, refers_to_regno_for_reload_p(), reg_class_subset_p(), reg_mentioned_p(), reg_or_subregno(), reg_overlap_mentioned_for_reload_p(), reg_renumber, reload::reg_rtx, RELOAD_FOR_OUTPUT, reload_inner_reg_of_subreg(), RELOAD_OTHER, remove_address_replacements(), replace_equiv_address_nv(), replace_reloads, replacements, rld, rtx_equal_p(), reload::secondary_in_icode, reload::secondary_in_reload, reload::secondary_out_icode, reload::secondary_out_reload, reload::secondary_p, secondary_reload_class(), sets_cc0_p(), static_reload_reg_p, subreg_lowpart_p(), subreg_regno(), subreg_regno_offset(), targetm, this_insn, this_insn_is_asm, type(), replacement::what, reload::when_needed, replacement::where, and word_mode.

Referenced by find_reloads(), find_reloads_address(), find_reloads_address_1(), find_reloads_address_part(), find_reloads_subreg_address(), and push_reload().

static void push_replacement ( rtx ,
int  ,
enum  machine_mode 
)
static
static void push_replacement ( )
static
Record an additional place we must replace a value
   for which we have already recorded a reload.
   RELOADNUM is the value returned by push_reload
   when the reload was recorded.
   This is used in insn patterns that use match_dup.   

References replacement::mode, n_replacements, replace_reloads, replacements, replacement::what, and replacement::where.

static int push_secondary_reload ( int  in_p,
rtx  x,
int  opnum,
int  optional,
enum reg_class  reload_class,
enum machine_mode  reload_mode,
enum reload_type  type,
enum insn_code *  picode,
secondary_reload_info prev_sri 
)
static
Determine if any secondary reloads are needed for loading (if IN_P is
   nonzero) or storing (if IN_P is zero) X to or from a reload register of
   register class RELOAD_CLASS in mode RELOAD_MODE.  If secondary reloads
   are needed, push them.

   Return the reload number of the secondary reload we made, or -1 if
   we didn't need one.  *PICODE is set to the insn_code to use if we do
   need a secondary reload.   

References get_secondary_mem(), secondary_reload_info::icode, reload::in, reload::in_reg, reload::inc, reload::inmode, insn_data, n_operands, n_reloads, reload::nocombine, reload::opnum, reload::optional, reload::out, reload::out_reg, reload::outmode, paradoxical_subreg_p(), secondary_reload_info::prev_sri, reload::rclass, reg_class_subset_p(), reload::reg_rtx, RELOAD_FOR_INPADDR_ADDRESS, RELOAD_FOR_INPUT_ADDRESS, RELOAD_FOR_OUTADDR_ADDRESS, RELOAD_FOR_OUTPUT_ADDRESS, RELOAD_OTHER, rld, reload::secondary_in_icode, reload::secondary_in_reload, reload::secondary_out_icode, reload::secondary_out_reload, reload::secondary_p, small_register_class_p(), targetm, type(), and reload::when_needed.

Referenced by push_reload().

static int refers_to_mem_for_reload_p ( rtx  )
static
static int refers_to_mem_for_reload_p ( )
static
Return nonzero if anything in X contains a MEM.  Look also for pseudo
   registers.   

References refers_to_mem_for_reload_p().

static int refers_to_regno_for_reload_p ( unsigned int  regno,
unsigned int  endregno,
rtx  x,
rtx loc 
)
static
Return nonzero if register in range [REGNO, ENDREGNO)
   appears either explicitly or implicitly in X
   other than being stored into (except for earlyclobber operands).

   References contained within the substructure at LOC do not count.
   LOC may be zero, meaning don't ignore anything.

   This is similar to refers_to_regno_p in rtlanal.c except that we
   look at equivalences for pseudos that didn't get hard registers.   

References earlyclobber_operand_p(), SET, subreg_nregs(), and subreg_regno().

Referenced by find_dummy_reload(), find_equiv_reg(), immune_p(), push_reload(), and reg_overlap_mentioned_for_reload_p().

static int reg_inc_found_and_valid_p ( unsigned int  regno,
unsigned int  endregno,
rtx  insn 
)
static
Return 1 if registers from REGNO to ENDREGNO are the subjects of a
   REG_INC note in insn INSN.  REGNO must refer to a hard register.   

Referenced by regno_clobbered_p().

int reg_overlap_mentioned_for_reload_p ( )
Nonzero if modifying X will affect IN.  If X is a register or a SUBREG,
   we check if any register number in X conflicts with the relevant register
   numbers.  If X is a constant, return 0.  If X is a MEM, return 1 iff IN
   contains a MEM (we don't bother checking for memory addresses that can't
   conflict because we expect this to be a rare case.

   This function is similar to reg_overlap_mentioned_p in rtlanal.c except
   that we look at equivalences for pseudos that didn't get hard registers.   

References refers_to_mem_for_reload_p(), refers_to_regno_for_reload_p(), reg_mentioned_p(), RTX_AUTOINC, rtx_equal_p(), subreg_nregs(), and subreg_regno_offset().

Referenced by choose_reload_regs(), combine_reloads(), find_equiv_reg(), and push_reload().

int regno_clobbered_p ( unsigned int  regno,
rtx  insn,
enum machine_mode  mode,
int  sets 
)
Return 1 if register REGNO is the subject of a clobber in insn INSN.
   If SETS is 1, also consider SETs.  If SETS is 2, enable checking
   REG_INC.  REGNO must refer to a hard register.   

References replacement::mode, reg_inc_found_and_valid_p(), and SET.

Referenced by choose_reload_regs(), emit_output_reload_insns(), find_reloads_address(), and find_reloads_address_1().

rtx reload_adjust_reg_for_mode ( )
Find the low part, with mode MODE, of a hard regno RELOADREG.   

References gen_rtx_REG().

Referenced by do_input_reload(), do_output_reload(), emit_output_reload_insns(), find_replacement(), reload_adjust_reg_for_temp(), and subst_reloads().

static bool reload_inner_reg_of_subreg ( )
static
Return true if X is a SUBREG that will need reloading of its SUBREG_REG
   expression.  MODE is the mode that X will be used in.  OUTPUT is true if
   the function is invoked for the output part of an enclosing reload.   

References subreg_regno().

Referenced by combine_reloads(), and push_reload().

int remove_address_replacements ( )
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,
   cancel the reloads that were supposed to load them.
   Return nonzero if we canceled any reloads.   

References deallocate_reload_reg(), reload::in, loc_mentioned_in_p(), memset(), n_reloads, n_replacements, replacements, rld, replacement::what, and replacement::where.

Referenced by choose_reload_regs(), and push_reload().

int safe_from_earlyclobber ( )
Similar, but calls decompose.   

References decompose(), and immune_p().

Referenced by constrain_operands().

enum reg_class scratch_reload_class ( )
ICODE is the insn_code of a reload pattern.  Check that it has exactly
   three operands, verify that operand 2 is an output operand, and return
   its register class.
   ??? We'd like to be able to handle any pattern with at least 2 operands,
   for zero or more scratch registers, but that needs more infrastructure.   

References insn_data, and n_operands.

Referenced by reload_adjust_reg_for_icode(), and secondary_reload_class().

reg_class_t secondary_reload_class ( bool  in_p,
reg_class_t  rclass,
enum machine_mode  mode,
rtx  x 
)
If a secondary reload is needed, return its class.  If both an intermediate
   register and a scratch register is needed, we return the class of the
   intermediate register.   

References secondary_reload_info::icode, secondary_reload_info::prev_sri, scratch_reload_class(), and targetm.

Referenced by choose_reload_regs(), emit_output_reload_insns(), memory_move_secondary_cost(), and push_reload().

static bool small_register_class_p ( )
inlinestatic
True if C is a non-empty register class that has too few registers
   to be safely used as a reload target class.   

References targetm.

Referenced by find_reloads(), find_reusable_reload(), and push_secondary_reload().

int strict_memory_address_addr_space_p ( enum machine_mode  mode,
rtx  addr,
addr_space_t  as 
)
Return 1 if ADDR is a valid memory address for mode MODE
   in address space AS, and check that each pseudo reg has the
   proper kind of hard reg.   

References replacement::mode, and targetm.

Referenced by constrain_operands(), find_reloads_address(), find_reloads_subreg_address(), get_secondary_mem(), offsettable_address_addr_space_p(), operand_subword(), and reload().

static rtx subst_indexed_address ( rtx  )
static
static rtx subst_indexed_address ( )
static
If ADDR is a sum containing a pseudo register that should be
   replaced with a constant (from reg_equiv_constant),
   return the result of doing so, and also apply the associative
   law so that the result is more likely to be a valid address.
   (But it is not guaranteed to be one.)

   Note that at most one register is replaced, even if more are
   replaceable.  Also, we try to put the result into a canonical form
   so it is more likely to be a valid address.

   In all other cases, return ADDR.   

References form_sum(), reg_renumber, and subst_indexed_address().

static rtx subst_reg_equivs ( rtx  ,
rtx   
)
static
static rtx subst_reg_equivs ( )
static
Find all pseudo regs appearing in AD
   that are eliminable in favor of equivalent values
   and do not have hard regs; replace them by their equivalents.
   INSN, if nonzero, is the insn in which we do the reload.  We put USEs in
   front of it for pseudos that we have to replace with stack slots.   

References emit_insn_before(), make_memloc(), num_not_at_initial_offset, rtx_equal_p(), subst_reg_equivs(), and subst_reg_equivs_changed.

void subst_reloads ( )
Substitute into the current INSN the registers into which we have reloaded
   the things that need reloading.  The array `replacements'
   contains the locations of all pointers that must be changed
   and says what to replace them with.

   Return the rtx that X translates into; usually X, but modified.   

References find_reg_note(), label_is_jump_target_p(), max_regno, replacement::mode, n_replacements, reload::optional, reload::reg_rtx, reload_adjust_reg_for_mode(), replacements, rld, replacement::what, and replacement::where.

Referenced by reload_as_needed().

void transfer_replacements ( )
Transfer all replacements that used to be in reload FROM to be in
   reload TO.   

References n_replacements, replacements, and replacement::what.

Referenced by find_reloads().

static void update_auto_inc_notes ( rtx  insn,
int  regno,
int  reloadnum 
)
static
Update the REG_INC notes for an insn.  It updates all REG_INC
   notes for the instruction which refer to REGNO the to refer
   to the reload number.

   INSN is the insn for which any REG_INC notes need updating.

   REGNO is the register number which has been reloaded.

   RELOADNUM is the reload number.   

References push_replacement().

Referenced by find_reloads_address_1().


Variable Documentation

int hard_regs_live_known
static
If hard_regs_live_known is nonzero,
   we can tell which hard regs are currently live,
   at least enough to succeed in choosing dummy reloads.   

Referenced by find_dummy_reload(), find_reloads(), and push_reload().

int n_earlyclobbers
All the "earlyclobber" operands of the current insn
   are recorded here.   

Referenced by choose_reload_regs(), earlyclobber_operand_p(), and find_reloads().

int output_reloadnum
static
On return from push_reload, holds the reload-number for the OUT
   operand, which can be different for that from the input operand.   

Referenced by find_reloads(), and push_reload().

rtx reload_earlyclobbers[MAX_RECOG_OPERANDS]
int reload_n_operands
const char* const reload_when_needed_name[]
static
Initial value:
{
"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"
}

Referenced by debug_reload_to_stream().

int replace_reloads
static
Replacing reloads.

   If `replace_reloads' is nonzero, then as each reload is recorded
   an entry is made for it in the table `replacements'.
   Then later `subst_reloads' can look through that table and
   perform all the replacements needed.   
Nonzero means record the places to replace.   

Referenced by find_reloads(), find_reloads_address(), find_reloads_subreg_address(), find_reloads_toplev(), push_reload(), and push_replacement().

rtx secondary_memlocs[NUM_MACHINE_MODES]
static
Save MEMs needed to copy from one class of registers to another.  One MEM
   is used per mode, but normally only one or two modes are ever used.

   We keep two versions, before and after register elimination.  The one
   after register elimination is record separately for each operand.  This
   is done in case the address is not valid to be sure that we separately
   reload each.   

Referenced by clear_secondary_mem(), and get_secondary_mem().

rtx secondary_memlocs_elim[NUM_MACHINE_MODES][MAX_RECOG_OPERANDS]
static
int secondary_memlocs_elim_used = 0
static

Referenced by find_reloads(), and get_secondary_mem().

short* static_reload_reg_p
static
Indexed by hard reg number,
   element is nonnegative if hard reg has been spilled.
   This vector is passed to `find_reloads' as an argument
   and is not changed here.   

Referenced by find_reloads(), and push_reload().

int subst_reg_equivs_changed
static
Set to 1 in subst_reg_equivs if it changes anything.   

Referenced by find_reloads_address(), and subst_reg_equivs().

rtx this_insn
static
The instruction we are doing reloads for;
   so we can test whether a register dies in it.   

Referenced by combine_reloads(), find_dummy_reload(), find_reloads(), find_reloads_address(), find_reloads_address_1(), and push_reload().

int this_insn_is_asm
static
Nonzero if this instruction is a user-specified asm with operands.   

Referenced by find_reloads(), and push_reload().