GCC Middle and Back End API Reference
reload1.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "tree.h"
#include "predict.h"
#include "df.h"
#include "memmodel.h"
#include "tm_p.h"
#include "optabs.h"
#include "regs.h"
#include "ira.h"
#include "recog.h"
#include "rtl-error.h"
#include "expr.h"
#include "addresses.h"
#include "cfgrtl.h"
#include "cfgbuild.h"
#include "reload.h"
#include "except.h"
#include "dumpfile.h"
#include "rtl-iter.h"
#include "function-abi.h"
Include dependency graph for reload1.cc:

Data Structures

struct  elim_table
 
struct  elim_table_1
 

Macros

#define spill_indirect_levels    (this_target_reload->x_spill_indirect_levels)
 
#define NUM_ELIMINABLE_REGS   ARRAY_SIZE (reg_eliminate_1)
 

Typedefs

typedef rtxrtx_p
 

Functions

static void replace_pseudos_in (rtx *, machine_mode, rtx)
 
static void maybe_fix_stack_asms (void)
 
static void copy_reloads (class insn_chain *)
 
static void calculate_needs_all_insns (int)
 
static int find_reg (class insn_chain *, int)
 
static void find_reload_regs (class insn_chain *)
 
static void select_reload_regs (void)
 
static void delete_caller_save_insns (void)
 
static void spill_failure (rtx_insn *, enum reg_class)
 
static void count_spilled_pseudo (int, int, int)
 
static void delete_dead_insn (rtx_insn *)
 
static void alter_reg (int, int, bool)
 
static void set_label_offsets (rtx, rtx_insn *, int)
 
static void check_eliminable_occurrences (rtx)
 
static void elimination_effects (rtx, machine_mode)
 
static rtx eliminate_regs_1 (rtx, machine_mode, rtx, bool, bool)
 
static int eliminate_regs_in_insn (rtx_insn *, int)
 
static void update_eliminable_offsets (void)
 
static void mark_not_eliminable (rtx, const_rtx, void *)
 
static void set_initial_elim_offsets (void)
 
static bool verify_initial_elim_offsets (void)
 
static void set_initial_label_offsets (void)
 
static void set_offsets_for_label (rtx_insn *)
 
static void init_eliminable_invariants (rtx_insn *, bool)
 
static void init_elim_table (void)
 
static void free_reg_equiv (void)
 
static void update_eliminables (HARD_REG_SET *)
 
static bool update_eliminables_and_spill (void)
 
static void elimination_costs_in_insn (rtx_insn *)
 
static void spill_hard_reg (unsigned int, int)
 
static int finish_spills (int)
 
static void scan_paradoxical_subregs (rtx)
 
static void count_pseudo (int)
 
static void order_regs_for_reload (class insn_chain *)
 
static void reload_as_needed (int)
 
static void forget_old_reloads_1 (rtx, const_rtx, void *)
 
static void forget_marked_reloads (regset)
 
static int reload_reg_class_lower (const void *, const void *)
 
static void mark_reload_reg_in_use (unsigned int, int, enum reload_type, machine_mode)
 
static void clear_reload_reg_in_use (unsigned int, int, enum reload_type, machine_mode)
 
static int reload_reg_free_p (unsigned int, int, enum reload_type)
 
static int reload_reg_free_for_value_p (int, int, int, enum reload_type, rtx, rtx, int, int)
 
static int free_for_value_p (int, machine_mode, int, enum reload_type, rtx, rtx, int, int)
 
static int allocate_reload_reg (class insn_chain *, int, int)
 
static int conflicts_with_override (rtx)
 
static void failed_reload (rtx_insn *, int)
 
static int set_reload_reg (int, int)
 
static void choose_reload_regs_init (class insn_chain *, rtx *)
 
static void choose_reload_regs (class insn_chain *)
 
static void emit_input_reload_insns (class insn_chain *, struct reload *, rtx, int)
 
static void emit_output_reload_insns (class insn_chain *, struct reload *, int)
 
static void do_input_reload (class insn_chain *, struct reload *, int)
 
static void do_output_reload (class insn_chain *, struct reload *, int)
 
static void emit_reload_insns (class insn_chain *)
 
static void delete_output_reload (rtx_insn *, int, int, rtx)
 
static void delete_address_reloads (rtx_insn *, rtx_insn *)
 
static void delete_address_reloads_1 (rtx_insn *, rtx, rtx_insn *)
 
static void inc_for_reload (rtx, rtx, rtx, poly_int64)
 
static void substitute (rtx *, const_rtx, rtx)
 
static bool gen_reload_chain_without_interm_reg_p (int, int)
 
static int reloads_conflict (int, int)
 
static rtx_insngen_reload (rtx, rtx, int, enum reload_type)
 
static rtx_insnemit_insn_if_valid_for_reload (rtx)
 
void init_reload (void)
 
class insn_chain * new_insn_chain (void)
 
void compute_use_by_pseudos (HARD_REG_SET *to, regset from)
 
static bool has_nonexceptional_receiver (void)
 
void grow_reg_equivs (void)
 
static void remove_init_insns ()
 
static bool will_delete_init_insn_p (rtx_insn *insn)
 
bool reload (rtx_insn *first, int global)
 
void calculate_elim_costs_all_insns (void)
 
static void mark_home_live_1 (int regno, machine_mode mode)
 
void mark_home_live (int regno)
 
static void note_reg_elim_costly (const_rtx x, rtx insn)
 
rtx eliminate_regs (rtx x, machine_mode mem_mode, rtx insn)
 
static void set_initial_eh_label_offset (rtx label)
 
bool elimination_target_reg_p (rtx x)
 
static bool strip_paradoxical_subreg (rtx *op_ptr, rtx *other_ptr)
 
static void fixup_eh_region_note (rtx_insn *insn, rtx_insn *prev, rtx_insn *next)
 
static int reload_reg_reaches_end_p (unsigned int regno, int reloadnum)
 
static bool reload_reg_rtx_reaches_end_p (rtx reg, int reloadnum)
 
static bool reloads_unique_chain_p (int r1, int r2)
 
bool function_invariant_p (const_rtx x)
 
static rtx replaced_subreg (rtx x)
 
static poly_int64 compute_reload_subreg_offset (machine_mode outermode, rtx subreg, machine_mode innermode)
 
void deallocate_reload_reg (int r)
 
static bool reload_adjust_reg_for_temp (rtx *reload_reg, rtx alt_reload_reg, enum reg_class new_class, machine_mode new_mode)
 
static bool reload_adjust_reg_for_icode (rtx *reload_reg, rtx alt_reload_reg, enum insn_code icode)
 
static bool inherit_piecemeal_p (int dest, int src, machine_mode mode)
 
static rtx_insnemit_insn_if_valid_for_reload_1 (rtx pat)
 

Variables

struct target_reload default_target_reload
 
static rtxreg_last_reload_reg
 
static regset_head reg_has_output_reload
 
static HARD_REG_SET reg_is_output_reload
 
static machine_mode * reg_max_ref_mode
 
static short * reg_old_renumber
 
static int reg_reloaded_contents [FIRST_PSEUDO_REGISTER]
 
static rtx_insnreg_reloaded_insn [FIRST_PSEUDO_REGISTER]
 
static HARD_REG_SET reg_reloaded_valid
 
static HARD_REG_SET reg_reloaded_dead
 
static int n_spills
 
static rtx spill_reg_rtx [FIRST_PSEUDO_REGISTER]
 
static rtx_insnspill_reg_store [FIRST_PSEUDO_REGISTER]
 
static rtx spill_reg_stored_to [FIRST_PSEUDO_REGISTER]
 
static short spill_reg_order [FIRST_PSEUDO_REGISTER]
 
static HARD_REG_SET bad_spill_regs
 
static HARD_REG_SET bad_spill_regs_global
 
static short spill_regs [FIRST_PSEUDO_REGISTER]
 
static HARD_REG_SETpseudo_previous_regs
 
static HARD_REG_SETpseudo_forbidden_regs
 
static HARD_REG_SET used_spill_regs
 
static int last_spill_reg
 
static rtx spill_stack_slot [FIRST_PSEUDO_REGISTER]
 
static poly_uint64 spill_stack_slot_width [FIRST_PSEUDO_REGISTER]
 
static regset_head spilled_pseudos
 
static regset_head changed_allocation_pseudos
 
static regset_head pseudos_counted
 
int reload_first_uid
 
int caller_save_needed
 
int reload_in_progress = 0
 
static struct obstack reload_obstack
 
static char * reload_startobj
 
static char * reload_firstobj
 
static char * reload_insn_firstobj
 
class insn_chain * reload_insn_chain
 
static bool need_dce
 
static class insn_chain * insns_need_reload
 
static struct elim_tablereg_eliminate = 0
 
static const struct elim_table_1 reg_eliminate_1 []
 
int num_not_at_initial_offset
 
static int num_eliminable
 
static int num_eliminable_invariants
 
static int first_label_num
 
static char * offsets_known_at
 
static poly_int64(* offsets_at )[NUM_ELIMINABLE_REGS]
 
vec< reg_equivs_t, va_gc > * reg_equivs
 
static vec< rtx_psubstitute_stack
 
static int num_labels
 
static class insn_chain * unused_insn_chains = 0
 
static basic_block elim_bb
 
static int something_needs_elimination
 
static int something_needs_operands_changed
 
static bool something_was_spilled
 
static int failure
 
static int * temp_pseudo_reg_arr
 
static int spill_cost [FIRST_PSEUDO_REGISTER]
 
static int spill_add_cost [FIRST_PSEUDO_REGISTER]
 
static int hard_regno_to_pseudo_regno [FIRST_PSEUDO_REGISTER]
 
static short reload_order [MAX_RELOADS]
 
static HARD_REG_SET used_spill_regs_local
 
static HARD_REG_SET reload_reg_unavailable
 
static HARD_REG_SET reload_reg_used
 
static HARD_REG_SET reload_reg_used_in_input_addr [MAX_RECOG_OPERANDS]
 
static HARD_REG_SET reload_reg_used_in_inpaddr_addr [MAX_RECOG_OPERANDS]
 
static HARD_REG_SET reload_reg_used_in_output_addr [MAX_RECOG_OPERANDS]
 
static HARD_REG_SET reload_reg_used_in_outaddr_addr [MAX_RECOG_OPERANDS]
 
static HARD_REG_SET reload_reg_used_in_input [MAX_RECOG_OPERANDS]
 
static HARD_REG_SET reload_reg_used_in_output [MAX_RECOG_OPERANDS]
 
static HARD_REG_SET reload_reg_used_in_op_addr
 
static HARD_REG_SET reload_reg_used_in_op_addr_reload
 
static HARD_REG_SET reload_reg_used_in_insn
 
static HARD_REG_SET reload_reg_used_in_other_addr
 
static HARD_REG_SET reload_reg_used_at_all
 
static HARD_REG_SET reload_reg_used_for_inherit
 
static HARD_REG_SET reg_used_in_insn
 
static char reload_inherited [MAX_RELOADS]
 
static rtx_insnreload_inheritance_insn [MAX_RELOADS]
 
static rtx reload_override_in [MAX_RELOADS]
 
static int reload_spill_index [MAX_RELOADS]
 
static rtx reload_reg_rtx_for_input [MAX_RELOADS]
 
static rtx reload_reg_rtx_for_output [MAX_RELOADS]
 
static rtx_insninput_reload_insns [MAX_RECOG_OPERANDS]
 
static rtx_insnother_input_address_reload_insns = 0
 
static rtx_insnother_input_reload_insns = 0
 
static rtx_insninput_address_reload_insns [MAX_RECOG_OPERANDS]
 
static rtx_insninpaddr_address_reload_insns [MAX_RECOG_OPERANDS]
 
static rtx_insnoutput_reload_insns [MAX_RECOG_OPERANDS]
 
static rtx_insnoutput_address_reload_insns [MAX_RECOG_OPERANDS]
 
static rtx_insnoutaddr_address_reload_insns [MAX_RECOG_OPERANDS]
 
static rtx_insnoperand_reload_insns = 0
 
static rtx_insnother_operand_reload_insns = 0
 
static rtx_insnother_output_reload_insns [MAX_RECOG_OPERANDS]
 
static rtx_insnnew_spill_reg_store [FIRST_PSEUDO_REGISTER]
 
static HARD_REG_SET reg_reloaded_died
 

Macro Definition Documentation

◆ NUM_ELIMINABLE_REGS

◆ spill_indirect_levels

#define spill_indirect_levels    (this_target_reload->x_spill_indirect_levels)

Typedef Documentation

◆ rtx_p

typedef rtx* rtx_p
Stack of addresses where an rtx has been changed.  We can undo the 
changes by popping items off the stack and restoring the original
value at each location. 

We use this simplistic undo capability rather than copy_rtx as copy_rtx
will not make a deep copy of a normally sharable rtx, such as
(const (plus (symbol_ref) (const_int))).  If such an expression appears
as R1 in gen_reload_chain_without_interm_reg_p, then a shared
rtx expression would be changed.  See PR 42431.   

Function Documentation

◆ allocate_reload_reg()

static int allocate_reload_reg ( class insn_chain * chain,
int r,
int last_reload )
static
Find a spill register to use as a reload register for reload R.
LAST_RELOAD is nonzero if this is the last reload for the insn being
processed.

Set rld[R].reg_rtx to the register allocated.

We return 1 if successful, or 0 if we couldn't find a spill reg and
we didn't change anything.   

References count, free_for_value_p(), hard_regno_nregs(), i, ira_bad_reload_regno(), last_spill_reg, n_spills, nr, r, reg_class_contents, reload_reg_free_p(), reload_reg_used, reload_reg_used_at_all, reload_reg_used_for_inherit, rld, set_reload_reg(), spill_reg_order, spill_regs, targetm, and TEST_HARD_REG_BIT.

Referenced by choose_reload_regs().

◆ alter_reg()

static void alter_reg ( int i,
int from_reg,
bool dont_share_p )
static

◆ calculate_elim_costs_all_insns()

◆ calculate_needs_all_insns()

◆ check_eliminable_occurrences()

static void check_eliminable_occurrences ( rtx x)
static
Descend through rtx X and verify that no references to eliminable registers
remain.  If any do remain, mark the involved register as not
eliminable.   

References elim_table::can_eliminate, check_eliminable_occurrences(), elim_table::from_rtx, GET_CODE, GET_RTX_FORMAT, GET_RTX_LENGTH, i, NUM_ELIMINABLE_REGS, reg_eliminate, REGNO, XEXP, XVECEXP, and XVECLEN.

Referenced by check_eliminable_occurrences(), eliminate_regs_in_insn(), and elimination_costs_in_insn().

◆ choose_reload_regs()

static void choose_reload_regs ( class insn_chain * chain)
static
Assign hard reg targets for the pseudo-registers we must reload
into hard regs for this insn.
Also output the instructions to copy them in and out of the hard regs.

For machines with register classes, we are responsible for
finding a reload reg in the proper class.   

References add_to_hard_reg_set(), allocate_reload_reg(), choose_reload_regs_init(), clear_reload_reg_in_use(), compute_reload_subreg_offset(), const0_rtx, CONSTANT_P, failed_reload(), find_equiv_reg(), frame_pointer_needed, free_for_value_p(), gcc_assert, gen_rtx_REG(), GET_CODE, GET_MODE, GET_MODE_SIZE(), GET_RTX_CLASS, get_secondary_mem(), HARD_FRAME_POINTER_REGNUM, HARD_REGISTER_P, hard_regno_nregs(), i, i1, known_ge, mark_reload_reg_in_use(), MAX, max_regno, MAX_RELOADS, MEM_P, memory_move_cost(), n_earlyclobbers, n_reloads, n_spills, nr, NULL, NULL_RTX, paradoxical_subreg_p(), qsort, r, REG_CAN_CHANGE_MODE_P, reg_class_contents, reg_class_superunion, reg_classes_intersect_p(), reg_has_output_reload, reg_is_output_reload, reg_last_reload_reg, reg_overlap_mentioned_for_reload_p(), REG_P, reg_reloaded_contents, reg_reloaded_dead, reg_reloaded_insn, reg_reloaded_valid, reg_used_in_insn, register_move_cost(), REGNO, regno_clobbered_p(), 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_OUTPUT, reload_inheritance_insn, reload_inherited, reload_order, RELOAD_OTHER, reload_override_in, reload_reg_class_lower(), reload_reg_unavailable, reload_reg_used_at_all, reload_reg_used_for_inherit, reload_spill_index, remove_address_replacements(), replaced_subreg(), rld, RTX_AUTOINC, rtx_equal_p(), secondary_reload_class(), SET_HARD_REG_BIT, SET_REGNO_REG_SET, set_reload_reg(), spill_reg_order, spill_reg_store, spill_regs, SUBREG_BYTE, SUBREG_REG, subreg_regno(), subreg_regno_offset(), targetm, TEST_HARD_REG_BIT, true_regnum(), and XEXP.

Referenced by reload_as_needed().

◆ choose_reload_regs_init()

◆ clear_reload_reg_in_use()

◆ compute_reload_subreg_offset()

static poly_int64 compute_reload_subreg_offset ( machine_mode outermode,
rtx subreg,
machine_mode innermode )
static
Compute the offset to pass to subreg_regno_offset, for a pseudo of
mode OUTERMODE that is available in a hard reg of mode INNERMODE.
SUBREG is non-NULL if the pseudo is a subreg whose reg is a pseudo,
otherwise it is NULL.   

References GET_MODE, paradoxical_subreg_p(), SUBREG_BYTE, subreg_lowpart_offset(), and SUBREG_REG.

Referenced by choose_reload_regs().

◆ compute_use_by_pseudos()

void compute_use_by_pseudos ( HARD_REG_SET * to,
regset from )
Small utility function to set all regs in hard reg set TO which are
allocated to pseudos in regset FROM.   

References add_to_hard_reg_set(), EXECUTE_IF_SET_IN_REG_SET, gcc_assert, ira_conflicts_p, PSEUDO_REGNO_MODE, r, reg_renumber, and reload_completed.

Referenced by choose_reload_regs_init(), finish_spills(), and reload_combine().

◆ conflicts_with_override()

static int conflicts_with_override ( rtx x)
static
Determine whether the reload reg X overlaps any rtx'es used for
overriding inheritance.  Return nonzero if so.   

References i, n_reloads, reg_overlap_mentioned_p(), and reload_override_in.

Referenced by emit_input_reload_insns().

◆ copy_reloads()

static void copy_reloads ( class insn_chain * chain)
static
Copy the global variables n_reloads and rld into the corresponding elts
of CHAIN.   

References n_reloads, reload(), reload_insn_firstobj, reload_obstack, and rld.

Referenced by calculate_needs_all_insns().

◆ count_pseudo()

static void count_pseudo ( int reg)
static

◆ count_spilled_pseudo()

static void count_spilled_pseudo ( int spilled,
int spilled_nregs,
int reg )
static
We decided to spill hard register SPILLED, which has a size of
SPILLED_NREGS.  Determine how pseudo REG, which is live during the insn,
is affected.  We will add it to SPILLED_PSEUDOS if necessary, and we will
update SPILL_COST/SPILL_ADD_COST.   

References gcc_assert, hard_regno_nregs(), hard_regno_to_pseudo_regno, ira_conflicts_p, PSEUDO_REGNO_MODE, r, REG_FREQ, reg_renumber, REGNO_REG_SET_P, SET_REGNO_REG_SET, spill_add_cost, spill_cost, and spilled_pseudos.

Referenced by find_reg().

◆ deallocate_reload_reg()

void deallocate_reload_reg ( int r)
Deallocate the reload register for reload R.  This is called from
remove_address_replacements.   

References clear_reload_reg_in_use(), r, reload_spill_index, rld, spill_reg_order, and true_regnum().

Referenced by remove_address_replacements().

◆ delete_address_reloads()

static void delete_address_reloads ( rtx_insn * dead_insn,
rtx_insn * current_insn )
static
We are going to delete DEAD_INSN.  Recursively delete loads of
reload registers used in DEAD_INSN that are not used till CURRENT_INSN.
CURRENT_INSN is being reloaded, so we have to check its reloads too.   

References CONST_INT_P, delete_address_reloads_1(), delete_related_insns(), GET_CODE, INTVAL, MEM_P, NEXT_INSN(), PREV_INSN(), rtx_equal_p(), SET_DEST, SET_SRC, single_set(), and XEXP.

Referenced by delete_output_reload().

◆ delete_address_reloads_1()

◆ delete_caller_save_insns()

static void delete_caller_save_insns ( void )
static
Delete all insns that were inserted by emit_caller_save_insns during
this iteration.   

References delete_insn(), reload_insn_chain, and unused_insn_chains.

Referenced by reload().

◆ delete_dead_insn()

static void delete_dead_insn ( rtx_insn * insn)
static
Delete an unneeded INSN and any previous insns who sole purpose is loading
data that is dead in INSN.   

References BLOCK_FOR_INSN(), find_regno_note(), GET_CODE, need_dce, PATTERN(), prev_active_insn(), reg_mentioned_p(), REG_P, REGNO, SET, SET_DEST, SET_INSN_DELETED, SET_SRC, and side_effects_p().

Referenced by remove_init_insns().

◆ delete_output_reload()

static void delete_output_reload ( rtx_insn * insn,
int j,
int last_reload_reg,
rtx new_reload_reg )
static
Delete a previously made output-reload whose result we now believe
is not needed.  First we double-check.

INSN is the insn now being processed.
LAST_RELOAD_REG is the hard register number for which we want to delete
the last output reload.
J is the reload-number that originally used REG.  The caller has made
certain that reload J doesn't use REG any longer for input.
NEW_RELOAD_REG is reload register that reload J is using for REG.   

References alter_reg(), AUTO_INC_DEC, CALL_INSN_FUNCTION_USAGE, CALL_P, count_occurrences(), delete_address_reloads(), delete_insn(), rtx_insn::deleted(), eliminate_regs(), find_regno_note(), gcc_assert, GET_CODE, GET_MODE, hard_regno_nregs(), i1, i2, ira_conflicts_p, ira_mark_allocation_change(), JUMP_P, LABEL_P, MEM_P, n_occurrences, n_reloads, NEXT_INSN(), NONJUMP_INSN_P, NOTE_INSN_BASIC_BLOCK_P, NULL, NULL_RTX, NUM_FIXED_BLOCKS, PATTERN(), PREV_INSN(), refers_to_regno_p(), REG_BASIC_BLOCK, reg_equiv_alt_mem_list, reg_equiv_memory_loc, reg_mentioned_p(), REG_N_DEATHS, REG_N_SETS(), REG_NREGS, reg_renumber, REGNO, reload_inherited, reload_override_in, rld, rtx_equal_p(), SET_DEST, single_set(), spill_reg_store, spill_reg_stored_to, SUBREG_REG, and XEXP.

Referenced by do_input_reload(), do_output_reload(), and emit_input_reload_insns().

◆ do_input_reload()

static void do_input_reload ( class insn_chain * chain,
struct reload * rl,
int j )
static

◆ do_output_reload()

static void do_output_reload ( class insn_chain * chain,
struct reload * rl,
int j )
static

◆ eliminate_regs()

rtx eliminate_regs ( rtx x,
machine_mode mem_mode,
rtx insn )
Scan X and replace any eliminable registers (such as fp) with a
replacement (such as sp), plus an offset.   

References eliminate_regs_1(), gcc_assert, NULL, reg_eliminate, and targetm.

Referenced by based_loc_descr(), compute_frame_pointer_to_fb_displacement(), delete_output_reload(), eliminate_regs_in_insn(), get_secondary_mem(), make_memloc(), reg_loc_descriptor(), reload(), reload_as_needed(), and vt_initialize().

◆ eliminate_regs_1()

static rtx eliminate_regs_1 ( rtx x,
machine_mode mem_mode,
rtx insn,
bool may_use_invariant,
bool for_costs )
static
Scan X and replace any eliminable registers (such as fp) with a
replacement (such as sp), plus an offset.

MEM_MODE is the mode of an enclosing MEM.  We need this to know how
much to adjust a register for, e.g., PRE_DEC.  Also, if we are inside a
MEM, we are allowed to replace a sum of a register and the constant zero
with the register, which we cannot do outside a MEM.  In addition, we need
to record the fact that a register is referenced outside a MEM.

If INSN is an insn, it is the insn containing X.  If we replace a REG
in a SET_DEST with an equivalent MEM and INSN is nonzero, write a
CLOBBER of the pseudo after INSN so find_equiv_regs will know that
the REG is being modified.

Alternatively, INSN may be a note (an EXPR_LIST or INSN_LIST).
That's used when we eliminate in expressions stored in notes.
This means, do not set ref_outside_mem even if the reference
is outside of MEMs.

If FOR_COSTS is true, we are being called before reload in order to
estimate the costs of keeping registers with an equivalence unallocated.

REG_EQUIV_MEM and REG_EQUIV_ADDRESS contain address that have had
replacements done assuming all offsets are at their initial values.  If
they are not, or if REG_EQUIV_ADDRESS is nonzero for a pseudo we
encounter, return the actual location so that find_reloads will do
the proper thing.   

References adjust_address_nv, alloc_reg_note(), alter_reg(), elim_table::can_eliminate, CASE_CONST_ANY, const0_rtx, CONST_INT_P, CONSTANT_P, copy_rtx(), current_function_decl, DEBUG_INSN_P, eliminate_regs_1(), form_sum(), elim_table::from_rtx, gcc_assert, gcc_unreachable, gen_rtvec_v(), gen_rtx_SUBREG(), GET_CODE, GET_MODE, GET_MODE_SIZE(), GET_RTX_FORMAT, GET_RTX_LENGTH, i, INTVAL, known_eq, MEM_P, memory_address_p, note_reg_elim_costly(), NULL, NULL_RTX, NUM_ELIMINABLE_REGS, paradoxical_subreg_p(), partial_subreg_p(), plus_constant(), elim_table::previous_offset, elim_table::ref_outside_mem, reg_eliminate, reg_equiv_constant, reg_equiv_init, reg_equiv_invariant, reg_equiv_memory_loc, reg_equivs, REG_NOTE_KIND, REG_P, reg_renumber, REGNO, replace_equiv_address_nv(), SET, shallow_copy_rtx(), SUBREG_BYTE, SUBREG_REG, elim_table::to_rtx, WORD_REGISTER_OPERATIONS, XEXP, XVEC, XVECEXP, and XVECLEN.

Referenced by calculate_elim_costs_all_insns(), eliminate_regs(), eliminate_regs_1(), eliminate_regs_in_insn(), elimination_costs_in_insn(), note_reg_elim_costly(), and replace_pseudos_in().

◆ eliminate_regs_in_insn()

static int eliminate_regs_in_insn ( rtx_insn * insn,
int replace )
static
Scan INSN and eliminate all eliminable registers in it.

If REPLACE is nonzero, do the replacement destructively.  Also
delete the insn as dead it if it is setting an eliminable register.

If REPLACE is zero, do all our allocations in reload_obstack.

If no eliminations were done and this insn doesn't require any elimination
processing (these are not identical conditions: it might be updating sp,
but not referencing fp; this needs to be seen during reload_as_needed so
that the offset between fp and sp can be taken into consideration), zero
is returned.  Otherwise, 1 is returned.   

References asm_noperands(), elim_table::can_eliminate, check_eliminable_occurrences(), CONST_INT_P, copy_insn(), copy_insn_1(), DEBUG_BIND_INSN_P, DEBUG_INSN_P, recog_data_d::dup_loc, recog_data_d::dup_num, eliminate_regs(), eliminate_regs_1(), elimination_effects(), emit_insn_after(), extract_insn(), elim_table::from_rtx, gcc_assert, gen_clobber(), gen_lowpart, GET_CODE, GET_MODE, i, INSN_CODE, insn_data, INSN_VAR_LOCATION_LOC, INTVAL, known_eq, MEM_P, recog_data_d::n_dups, recog_data_d::n_operands, NULL_RTX, NUM_ELIMINABLE_REGS, elim_table::offset, offset, OP_IN, recog_data_d::operand, recog_data_d::operand_loc, recog_data_d::operand_type, PATTERN(), plus_constant(), elim_table::previous_offset, recog(), recog_data, recog_memoized(), elim_table::ref_outside_mem, reg_eliminate, REG_NOTE_KIND, REG_NOTES, REG_P, REGNO, SET, SET_DEST, SET_SRC, single_set(), subreg_lowpart_p(), SUBREG_REG, elim_table::to_rtx, trunc_int_for_mode(), validate_change(), and XEXP.

Referenced by calculate_needs_all_insns(), and reload_as_needed().

◆ elimination_costs_in_insn()

static void elimination_costs_in_insn ( rtx_insn * insn)
static

◆ elimination_effects()

static void elimination_effects ( rtx x,
machine_mode mem_mode )
static

◆ elimination_target_reg_p()

bool elimination_target_reg_p ( rtx x)
Return true if X is used as the target register of an elimination.   

References elim_table::can_eliminate, NUM_ELIMINABLE_REGS, reg_eliminate, and elim_table::to_rtx.

Referenced by find_reloads().

◆ emit_input_reload_insns()

static void emit_input_reload_insns ( class insn_chain * chain,
struct reload * rl,
rtx old,
int j )
static
Generate insns to perform reload RL, which is for the insn in CHAIN and
has the number J.  OLD contains the value to be used as input.   

References alter_reg(), asm_noperands(), AUTO_INC_DEC, cfun, conflicts_with_override(), CONSTANT_P, constrain_operands(), copy_reg_eh_region_note_forward(), count_occurrences(), dead_or_set_p(), DEBUG_BIND_INSN_P, DEBUG_INSN_P, delete_output_reload(), emit_insn(), end_sequence(), extract_insn(), find_reg_note(), free_for_value_p(), gcc_assert, gcc_unreachable, gen_lowpart_SUBREG(), gen_reload(), GET_CODE, get_enabled_alternatives(), get_insns(), GET_MODE, secondary_reload_info::icode, inc_for_reload(), inpaddr_address_reload_insns, input_address_reload_insns, input_reload_insns, INSN_VAR_LOCATION_LOC, ira_conflicts_p, ira_mark_allocation_change(), NEXT_INSN(), NONJUMP_INSN_P, NOTE_P, NULL, num_not_at_initial_offset, operand_reload_insns, other_input_address_reload_insns, other_input_reload_insns, other_operand_reload_insns, outaddr_address_reload_insns, output_address_reload_insns, PATTERN(), PREV_INSN(), secondary_reload_info::prev_sri, push_to_sequence(), reg_equiv_constant, reg_equiv_mem, reg_equiv_memory_loc, REG_N_DEATHS, REG_N_SETS(), REG_P, reg_renumber, REGNO, reload_adjust_reg_for_icode(), reload_adjust_reg_for_temp(), RELOAD_FOR_INPADDR_ADDRESS, RELOAD_FOR_INPUT, RELOAD_FOR_INPUT_ADDRESS, RELOAD_FOR_OPADDR_ADDR, RELOAD_FOR_OPERAND_ADDRESS, RELOAD_FOR_OTHER_ADDRESS, RELOAD_FOR_OUTADDR_ADDRESS, RELOAD_FOR_OUTPUT_ADDRESS, reload_inherited, RELOAD_OTHER, reload_override_in, reload_reg_rtx_for_input, rld, rtx_equal_p(), SET, SET_DEST, SET_SRC, simplify_replace_rtx(), spill_reg_store, spill_reg_stored_to, SUBREG_REG, targetm, and XEXP.

Referenced by do_input_reload().

◆ emit_insn_if_valid_for_reload()

static rtx_insn * emit_insn_if_valid_for_reload ( rtx pat)
static
Go through the motions to emit INSN and test if it is strictly valid.
Return the emitted insn if valid, else return NULL.   

References emit_insn_if_valid_for_reload(), emit_insn_if_valid_for_reload_1(), gen_hard_reg_clobber(), gen_rtvec(), GET_CODE, INVALID_REGNUM, NULL, SET, and targetm.

Referenced by emit_insn_if_valid_for_reload(), and gen_reload().

◆ emit_insn_if_valid_for_reload_1()

static rtx_insn * emit_insn_if_valid_for_reload_1 ( rtx pat)
static

◆ emit_output_reload_insns()

◆ emit_reload_insns()

◆ failed_reload()

static void failed_reload ( rtx_insn * insn,
int r )
static
Give an error message saying we failed to find a reload for INSN,
and clear out reload R.   

References asm_noperands(), error_for_asm(), fatal_insn, PATTERN(), r, and rld.

Referenced by choose_reload_regs().

◆ find_reg()

◆ find_reload_regs()

static void find_reload_regs ( class insn_chain * chain)
static
Find more reload regs to satisfy the remaining need of an insn, which
is given by CHAIN.
Do it by ascending class number, since otherwise a reg
might be spilled for a big class and might fail to count
for a smaller class even though it belongs to that class.   

References CLEAR_HARD_REG_SET, dump_file, failure, find_reg(), i, INSN_UID(), n_reloads, order_regs_for_reload(), qsort, r, REG_NREGS, REGNO, reload(), reload_order, reload_reg_class_lower(), rld, spill_failure(), used_spill_regs, and used_spill_regs_local.

Referenced by select_reload_regs().

◆ finish_spills()

static int finish_spills ( int global)
static
After spill_hard_reg was called and/or find_reload_regs was run for all
insns that need reloads, this function is used to actually spill pseudo
registers and try to reallocate them.  It also sets up the spill_regs
array for use by choose_reload_regs.

GLOBAL nonzero means we should attempt to reallocate any pseudo registers
that we displace from hard registers.   

References alter_reg(), AND_COMPL_REG_SET, bad_spill_regs_global, changed_allocation_pseudos, CLEAR_REG_SET, CLEAR_REGNO_REG_SET, compute_use_by_pseudos(), df_regs_ever_live_p(), df_set_regs_ever_live(), dump_file, EXECUTE_IF_SET_IN_REG_SET, i, insns_need_reload, ira_conflicts_p, ira_mark_allocation_change(), ira_reassign_pseudos(), max_regno, n_spills, num_eliminable, pseudo_forbidden_regs, pseudo_previous_regs, reg_old_renumber, reg_renumber, REG_SET_TO_HARD_REG_SET, reload_insn_chain, SET_HARD_REG_BIT, SET_REGNO_REG_SET, spill_reg_order, spill_regs, spilled_pseudos, temp_pseudo_reg_arr, TEST_HARD_REG_BIT, and used_spill_regs.

Referenced by reload().

◆ fixup_eh_region_note()

static void fixup_eh_region_note ( rtx_insn * insn,
rtx_insn * prev,
rtx_insn * next )
static
A subroutine of reload_as_needed.  If INSN has a REG_EH_REGION note,
examine all of the reload insns between PREV and NEXT exclusive, and
annotate all that may trap.   

References copy_reg_eh_region_note_forward(), find_reg_note(), insn_could_throw_p(), NEXT_INSN(), NULL, NULL_RTX, and remove_note().

Referenced by reload_as_needed().

◆ forget_marked_reloads()

static void forget_marked_reloads ( regset regs)
static

◆ forget_old_reloads_1()

static void forget_old_reloads_1 ( rtx x,
const_rtx ,
void * data )
static
Discard all record of any value reloaded from X,
or reloaded in X from someplace else;
unless X is an output reload reg of the current insn.

X may be a hard reg (the reload reg)
or it may be a pseudo reg that was reloaded from.

When DATA is non-NULL just mark the registers in regset
to be forgotten later.   

References CLEAR_HARD_REG_BIT, GET_CODE, i, n_reloads, nr, reg_has_output_reload, reg_is_output_reload, reg_last_reload_reg, REG_NREGS, REG_P, reg_reloaded_valid, REGNO, REGNO_REG_SET_P, SET_REGNO_REG_SET, spill_reg_store, SUBREG_REG, and TEST_HARD_REG_BIT.

Referenced by emit_output_reload_insns(), emit_reload_insns(), and reload_as_needed().

◆ free_for_value_p()

static int free_for_value_p ( int regno,
machine_mode mode,
int opnum,
enum reload_type type,
rtx value,
rtx out,
int reloadnum,
int ignore_address_reloads )
static
Return 1 if the value in reload reg REGNO, as used by a reload
needed for the part of the insn specified by OPNUM and TYPE,
may be used to load VALUE into it.

MODE is the mode in which the register is used, this is needed to
determine how many hard regs to test.

Other read-only reloads with the same value do not conflict
unless OUT is nonzero and these other reloads have to live while
output reloads live.
If OUT is CONST0_RTX, this is a special case: it means that the
test should not be for using register REGNO as reload register, but
for copying from register REGNO into the reload register.

RELOADNUM is the number of the reload we want to load this value for;
a reload does not conflict with itself.

When IGNORE_ADDRESS_RELOADS is set, we cannot have conflicts with
reloads that load an address for the very reload we are considering.

The caller has to make sure that there is no conflict with the return
register.   

References hard_regno_nregs(), and reload_reg_free_for_value_p().

Referenced by allocate_reload_reg(), choose_reload_regs(), and emit_input_reload_insns().

◆ free_reg_equiv()

static void free_reg_equiv ( void )
static
Indicate that we no longer have known memory locations or constants.
Free all data involved in tracking these.   

References free(), free_EXPR_LIST_list(), i, offsets_at, offsets_known_at, reg_equiv_alt_mem_list, reg_equivs, and vec_free().

Referenced by reload().

◆ function_invariant_p()

bool function_invariant_p ( const_rtx x)
Return true if the rtx X is invariant over the current function.   
??? Actually, the places where we use this expect exactly what is
tested here, and not everything that is function invariant.  In
particular, the frame pointer and arg pointer are special cased;
pic_offset_table_rtx is not, and we must not spill these things to
memory.   

References arg_pointer_rtx, CONSTANT_P, frame_pointer_rtx, GET_CODE, and XEXP.

Referenced by df_find_single_def_src(), elimination_effects(), init_eliminable_invariants(), iv_analyze_op(), setup_reg_equiv(), and simple_rhs_p().

◆ gen_reload()

static rtx_insn * gen_reload ( rtx out,
rtx in,
int opnum,
enum reload_type type )
static

◆ gen_reload_chain_without_interm_reg_p()

static bool gen_reload_chain_without_interm_reg_p ( int r1,
int r2 )
static
The function returns TRUE if chain of reload R1 and R2 (in any
  order) can be evaluated without usage of intermediate register for
  the reload containing another reload.  It is important to see
  gen_reload to understand what the function is trying to do.  As an
  example, let us have reload chain

     r2: const
     r1: <something> + const

  and reload R2 got reload reg HR.  The function returns true if
  there is a correct insn HR = HR + <something>.  Otherwise,
  gen_reload will use intermediate register (and this is the reload
  reg for R1) to reload <something>.

  We need this function to find a conflict for chain reloads.  In our
  example, if HR = HR + <something> is incorrect insn, then we cannot
  use HR as a reload register for R2.  If we do use it then we get a
  wrong code:

     HR = const
     HR = <something>
     HR = HR + HR

References CONSTANT_P, constrain_operands(), delete_insns_since(), emit_insn(), extract_insn(), gcc_assert, gen_rtx_REG(), GET_CODE, get_enabled_alternatives(), get_last_insn(), last, MEM_P, recog_memoized(), reg_mentioned_p(), REG_P, rld, strip_paradoxical_subreg(), substitute(), substitute_stack, and XEXP.

Referenced by reloads_conflict().

◆ grow_reg_equivs()

void grow_reg_equivs ( void )
Grow (or allocate) the REG_EQUIVS array from its current size (which may be
zero elements) to MAX_REG_NUM elements.

Initialize all new fields to NULL and update REG_EQUIVS_SIZE.   

References i, max_reg_num(), max_regno, reg_equivs, vec_safe_length(), and vec_safe_reserve().

Referenced by emit_move_list(), fix_reg_equiv_init(), init_eliminable_invariants(), ira(), and reload().

◆ has_nonexceptional_receiver()

static bool has_nonexceptional_receiver ( void )
static
Determine if the current function has an exception receiver block
that reaches the exit block via non-exceptional edges   

References bb_has_abnormal_pred(), cfun, EXIT_BLOCK_PTR_FOR_FN, basic_block_def::flags, FOR_EACH_BB_FN, FOR_EACH_EDGE, free(), n_basic_blocks_for_fn, basic_block_def::preds, and worklist.

Referenced by reload().

◆ inc_for_reload()

static void inc_for_reload ( rtx reloadreg,
rtx in,
rtx value,
poly_int64 inc_amount )
static
Output reload-insns to reload VALUE into RELOADREG.
VALUE is an autoincrement or autodecrement RTX whose operand
is a register or memory location;
so reloading involves incrementing that location.
IN is either identical to VALUE, or some cheaper place to reload from.

INC_AMOUNT is the number to increment or decrement by (always positive).
This cannot be deduced from VALUE.   

References add_insn(), CONST_INT_P, constrain_operands(), delete_insns_since(), emit_insn(), extract_insn(), find_replacement(), gcc_assert, gen_add2_insn(), gen_int_mode(), gen_move_insn(), gen_sub2_insn(), GET_CODE, get_enabled_alternatives(), get_last_insn(), GET_MODE, INTVAL, last, recog_memoized(), reg_last_reload_reg, REG_P, REGNO, and XEXP.

Referenced by emit_input_reload_insns().

◆ inherit_piecemeal_p()

static bool inherit_piecemeal_p ( int dest,
int src,
machine_mode mode )
static
A reload copies values of MODE from register SRC to register DEST.
Return true if it can be treated for inheritance purposes like a
group of reloads, each one reloading a single hard register.  The
caller has already checked that (reg:MODE SRC) and (reg:MODE DEST)
occupy the same number of hard registers.   

References REG_CAN_CHANGE_MODE_P, and reg_raw_mode.

Referenced by emit_reload_insns().

◆ init_elim_table()

static void init_elim_table ( void )
static

◆ init_eliminable_invariants()

static void init_eliminable_invariants ( rtx_insn * first,
bool do_subregs )
static
Find all the pseudo registers that didn't get hard regs
but do have known equivalent constants or memory slots.
These include parameters (known equivalent to parameter slots)
and cse'd or loop-moved constant memory addresses.

Record constant equivalents in reg_equiv_constant
so they will be substituted by find_reloads.
Record memory equivalents in reg_mem_equiv so they can
be substituted eventually by altering the REG-rtx's.   
Look for REG_EQUIV notes; record what each pseudo is equivalent
to.  If DO_SUBREGS is true, also find all paradoxical subregs and
find largest such for each pseudo.  FIRST is the head of the insn
list.   

References arg_pointer_rtx, CONSTANT_P, copy_rtx(), dump_file, find_reg_note(), first_label_num, force_const_mem(), frame_pointer_rtx, function_invariant_p(), GET_CODE, get_first_label_num(), GET_MODE, grow_reg_equivs(), i, INSN_P, LAST_VIRTUAL_REGISTER, LEGITIMATE_PIC_OPERAND_P, max_label_num(), max_regno, memory_operand(), NEXT_INSN(), NONDEBUG_INSN_P, NULL, NULL_RTX, num_eliminable_invariants, NUM_ELIMINABLE_REGS, num_labels, offsets_at, offsets_known_at, PATTERN(), print_inline_rtx(), PUT_MODE(), reg_equiv_constant, reg_equiv_init, reg_equiv_invariant, reg_equiv_memory_loc, reg_max_ref_mode, REG_P, REGNO, scan_paradoxical_subregs(), SET_DEST, single_set(), targetm, and XEXP.

Referenced by calculate_elim_costs_all_insns(), and reload().

◆ init_reload()

void init_reload ( void )

◆ mark_home_live()

void mark_home_live ( int regno)
Mark the slots in regs_ever_live for the hard regs
used by pseudo-reg number REGNO.   

References mark_home_live_1(), PSEUDO_REGNO_MODE, and reg_renumber.

Referenced by allocno_reload_assign(), and reload().

◆ mark_home_live_1()

static void mark_home_live_1 ( int regno,
machine_mode mode )
static
Mark the slots in regs_ever_live for the hard regs used by
pseudo-reg number REGNO, accessed in MODE.   

References df_set_regs_ever_live(), end_hard_regno(), i, and reg_renumber.

Referenced by mark_home_live(), and scan_paradoxical_subregs().

◆ mark_not_eliminable()

static void mark_not_eliminable ( rtx dest,
const_rtx x,
void * data )
static
Given X, a SET or CLOBBER of DEST, if DEST is the target of a register
replacement we currently believe is valid, mark it as not eliminable if X
modifies DEST in any way other than by adding a constant integer to it.

If DEST is the frame pointer, we do nothing because we assume that
all assignments to the hard frame pointer are nonlocal gotos and are being
done at a time when they are valid and do not disturb anything else.
Some machines want to eliminate a fake argument pointer with either the
frame or stack pointer.  Assignments to the hard frame pointer must not
prevent this elimination.

Called via note_stores from reload before starting its passes to scan
the insns of the function.   

References elim_table::can_eliminate, elim_table::can_eliminate_previous, CONST_INT_P, GET_CODE, hard_frame_pointer_rtx, i, num_eliminable, NUM_ELIMINABLE_REGS, reg_eliminate, SET, SET_SRC, SUBREG_REG, elim_table::to_rtx, and XEXP.

Referenced by reload().

◆ mark_reload_reg_in_use()

◆ maybe_fix_stack_asms()

static void maybe_fix_stack_asms ( void )
static
Yet another special case.  Unfortunately, reg-stack forces people to
write incorrect clobbers in asm statements.  These clobbers must not
cause the register to appear in bad_spill_regs, otherwise we'll call
fatal_insn later.  We clear the corresponding regnos in the live
register sets to avoid this.
The whole thing is rather sick, I'm afraid.   

References ADDR_SPACE_GENERIC, asm_noperands(), base_reg_class(), CLEAR_HARD_REG_SET, CLEAR_REGNO_REG_SET, constraints, decode_asm_operands(), GET_CODE, i, INSN_P, NULL, recog_data_d::operand, recog_data_d::operand_loc, PATTERN(), recog_data, reg_class_contents, reg_class_subunion, REGNO, reload_insn_chain, SET_HARD_REG_BIT, TEST_HARD_REG_BIT, XEXP, XVECEXP, and XVECLEN.

Referenced by reload().

◆ new_insn_chain()

class insn_chain * new_insn_chain ( void )
Allocate an empty insn_chain structure.   

References INIT_REG_SET, reload_obstack, and unused_insn_chains.

Referenced by build_insn_chain(), and insert_one_insn().

◆ note_reg_elim_costly()

static void note_reg_elim_costly ( const_rtx x,
rtx insn )
static
This function examines every reg that occurs in X and adjusts the
costs for its elimination which are gathered by IRA.  INSN is the
insn in which X occurs.  We do not recurse into MEM expressions.   

References elim_bb, eliminate_regs_1(), FOR_EACH_SUBRTX, ira_adjust_equiv_reg_cost(), MEM_P, optimize_bb_for_speed_p(), reg_equiv_init, reg_equiv_invariant, REG_FREQ_FROM_BB, REG_P, REGNO, and set_src_cost().

Referenced by eliminate_regs_1(), and elimination_costs_in_insn().

◆ order_regs_for_reload()

static void order_regs_for_reload ( class insn_chain * chain)
static
Calculate the SPILL_COST and SPILL_ADD_COST arrays and determine the
contents of BAD_SPILL_REGS for the insn described by CHAIN.   

References bad_spill_regs, CLEAR_REG_SET, count_pseudo(), EXECUTE_IF_SET_IN_REG_SET, fixed_reg_set, hard_regno_to_pseudo_regno, i, pseudos_counted, REG_SET_TO_HARD_REG_SET, spill_add_cost, and spill_cost.

Referenced by find_reload_regs().

◆ reload()

bool reload ( rtx_insn * first,
int global )
Main entry point for the reload pass.

FIRST is the first insn of the function being compiled.

GLOBAL nonzero means we were called from global_alloc
and should attempt to reallocate any pseudoregs that we
displace from hard regs we will use for reloads.
If GLOBAL is zero, we do not have enough information to do that,
so any pseudo reg that is spilled must go to the stack.

Return value is TRUE if reload likely left dead insns in the
stream and a DCE pass should be run to elimiante them.  Else the
return value is FALSE.   

References add_auto_inc_notes(), alter_reg(), asm_noperands(), assign_stack_local(), AUTO_INC_DEC, bad_spill_regs_global, bitmap_clear_bit(), bitmap_empty_p(), bitmap_ones(), calculate_needs_all_insns(), CALL_INSN_FUNCTION_USAGE, CALL_P, caller_save_needed, elim_table::can_eliminate, cfun, changed_allocation_pseudos, cleanup_subreg_operands(), CLEAR_HARD_REG_SET, CLEAR_REG_SET, clear_secondary_mem(), commit_edge_insertions(), CONSTANT_P, constrain_operands(), crtl, DEBUG_BIND_INSN_P, delete_caller_save_insns(), delete_insn(), df_get_live_in(), df_insn_rescan_debug_internal(), DF_REF_INSN, DF_REF_NEXT_REG, DF_REG_USE_CHAIN, df_set_regs_ever_live(), eliminate_regs(), emit_note(), error_for_asm(), extract_insn(), failure, find_many_sub_basic_blocks(), find_reg_note(), finish_spills(), fixed_regs, fixup_abnormal_edges(), FOR_EACH_BB_FN, frame_pointer_needed, free(), free_reg_equiv(), elim_table::from, gcc_assert, gen_rtx_UNKNOWN_VAR_LOC, GET_CODE, get_enabled_alternatives(), get_frame_size(), get_max_uid(), GET_MODE, grow_reg_equivs(), HARD_FRAME_POINTER_IS_FRAME_POINTER, HARD_FRAME_POINTER_REGNUM, has_nonexceptional_receiver(), i, init_elim_table(), init_eliminable_invariants(), init_recog(), init_save_areas(), inserted, INSN_P, INSN_VAR_LOCATION_LOC, insns_need_reload, ira_conflicts_p, ira_sort_regnos_for_alter_reg(), known_eq, last_basic_block_for_fn, last_spill_reg, LAST_VIRTUAL_REGISTER, LOCAL_REGNO, mark_elimination(), mark_home_live(), mark_not_eliminable(), max_regno, MAY_HAVE_DEBUG_BIND_INSNS, maybe_fix_stack_asms(), MEM_ADDR_SPACE, MEM_ATTRS, MEM_COPY_ATTRIBUTES, MEM_NOTRAP_P, MEM_P, n_spills, need_dce, NEXT_INSN(), NONJUMP_INSN_P, note_pattern_stores(), NULL, NULL_RTX, num_eliminable, NUM_ELIMINABLE_REGS, PATTERN(), pseudo_forbidden_regs, pseudo_previous_regs, PUT_CODE, reg_eliminate, reg_equiv_address, reg_equiv_constant, reg_equiv_init, reg_equiv_invariant, reg_equiv_mem, reg_equiv_memory_loc, REG_FUNCTION_VALUE_P, reg_max_ref_mode, REG_NOTE_KIND, REG_NOTES, reg_old_renumber, REG_P, reg_renumber, REG_USERVAR_P, REGNO, REGNO_POINTER_ALIGN, regno_reg_rtx, reload_as_needed(), reload_completed, reload_first_uid, reload_firstobj, reload_in_progress, reload_obstack, reload_startobj, remove_init_insns(), replace_pseudos_in(), save_call_clobbered_regs(), select_reload_regs(), SET, SET_DEST, SET_HARD_REG_BIT, set_initial_elim_offsets(), set_initial_label_offsets(), SET_SRC, setup_save_areas(), simplify_replace_rtx(), something_needs_elimination, something_needs_operands_changed, something_was_spilled, spill_hard_reg, spill_regs, spill_stack_slot, spill_stack_slot_width, spilled_pseudos, stack_pointer_rtx, strict_memory_address_addr_space_p(), substitute_stack, targetm, temp_pseudo_reg_arr, elim_table::to, unshare_all_rtl_again(), unused_insn_chains, update_eliminables_and_spill(), used_spill_regs, verify_initial_elim_offsets(), and XEXP.

Referenced by copy_reloads(), do_reload(), find_reg(), and find_reload_regs().

◆ reload_adjust_reg_for_icode()

static bool reload_adjust_reg_for_icode ( rtx * reload_reg,
rtx alt_reload_reg,
enum insn_code icode )
static
Check if *RELOAD_REG is suitable as a scratch register for the reload
pattern with insn_code ICODE, or alternatively, if alt_reload_reg is
nonzero, if that is suitable.  On success, change *RELOAD_REG to the
adjusted register, and return true.  Otherwise, return false.   

References insn_data, new_mode(), reload_adjust_reg_for_temp(), and scratch_reload_class().

Referenced by emit_input_reload_insns().

◆ reload_adjust_reg_for_temp()

static bool reload_adjust_reg_for_temp ( rtx * reload_reg,
rtx alt_reload_reg,
enum reg_class new_class,
machine_mode new_mode )
static
Check if *RELOAD_REG is suitable as an intermediate or scratch register
of class NEW_CLASS with mode NEW_MODE.  Or alternatively, if alt_reload_reg
is nonzero, if that is suitable.  On success, change *RELOAD_REG to the
adjusted register, and return true.  Otherwise, return false.   

References GET_MODE, hard_regno_nregs(), new_mode(), reg_class_contents, REG_NREGS, REGNO, reload_adjust_reg_for_mode(), targetm, and TEST_HARD_REG_BIT.

Referenced by emit_input_reload_insns(), and reload_adjust_reg_for_icode().

◆ reload_as_needed()

static void reload_as_needed ( int live_known)
static
Reload pseudo-registers into hard regs around each insn as needed.
Additional register load insns are output before the insn that needs it
and perhaps store insns after insns that modify the reloaded pseudo reg.

reg_last_reload_reg and reg_reloaded_contents keep track of
which registers are already available in reload registers.
We update these for the reloads that we perform,
as the insns are scanned.   

References add_reg_note(), asm_noperands(), CALL_P, cancel_changes(), cfun, choose_reload_regs(), CLEAR_HARD_REG_SET, CLEAR_REG_SET, confirm_change_group(), constrain_operands(), count_occurrences(), delete_insn(), eliminate_regs(), eliminate_regs_in_insn(), emit_note(), emit_reload_insns(), error_for_asm(), extract_insn(), find_reg_note(), find_reloads(), fixup_args_size_notes(), fixup_eh_region_note(), forget_marked_reloads(), forget_old_reloads_1(), free(), get_args_size(), GET_CODE, get_enabled_alternatives(), GET_MODE, i, INIT_REG_SET, INSN_P, LABEL_P, max_regno, MEM_P, n_reloads, NEXT_INSN(), NONJUMP_INSN_P, NOTE_P, note_stores(), NULL, NULL_RTX, num_eliminable, num_eliminable_invariants, PATTERN(), PREV_INSN(), recog_memoized(), reg_has_output_reload, reg_is_output_reload, reg_last_reload_reg, REG_NOTE_KIND, REG_NOTES, reg_reloaded_contents, reg_reloaded_insn, reg_reloaded_valid, reg_set_p(), REGNO, reload_insn_chain, remove_note(), reorder_insns_nobb(), rld, SET_HARD_REG_BIT, set_initial_elim_offsets(), set_offsets_for_label(), SET_REGNO_REG_SET, spill_indirect_levels, spill_reg_order, spill_reg_rtx, spill_reg_store, subst_reloads(), TEST_HARD_REG_BIT, unlink_insn_chain(), update_eliminable_offsets(), validate_replace_rtx_group(), verify_changes(), will_delete_init_insn_p(), and XEXP.

Referenced by reload().

◆ reload_reg_class_lower()

static int reload_reg_class_lower ( const void * r1p,
const void * r2p )
static
Comparison function for qsort to decide which of two reloads
should be handled first.  *P1 and *P2 are the reload numbers.   

References reg_class_size, and rld.

Referenced by choose_reload_regs(), and find_reload_regs().

◆ reload_reg_free_for_value_p()

static int reload_reg_free_for_value_p ( int start_regno,
int regno,
int opnum,
enum reload_type type,
rtx value,
rtx out,
int reloadnum,
int ignore_address_reloads )
static
Subroutine of free_for_value_p, used to check a single register.
START_REGNO is the starting regno of the full reload register
(possibly comprising multiple hard registers) that we are considering.   

References const0_rtx, earlyclobber_operand_p(), i, n_reloads, NULL_RTX, REG_NREGS, REG_P, 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_OTHER, reload_reg_unavailable, rld, rtx_equal_p(), TEST_HARD_REG_BIT, and true_regnum().

Referenced by free_for_value_p().

◆ reload_reg_free_p()

◆ reload_reg_reaches_end_p()

static int reload_reg_reaches_end_p ( unsigned int regno,
int reloadnum )
static

◆ reload_reg_rtx_reaches_end_p()

static bool reload_reg_rtx_reaches_end_p ( rtx reg,
int reloadnum )
static
Like reload_reg_reaches_end_p, but check that the condition holds for
every register in REG.   

References END_REGNO(), i, REGNO, and reload_reg_reaches_end_p().

Referenced by emit_output_reload_insns(), and emit_reload_insns().

◆ reloads_conflict()

static int reloads_conflict ( int r1,
int r2 )
static
Return 1 if the reloads denoted by R1 and R2 cannot share a register.
Return 0 otherwise.

This function uses the same algorithm as reload_reg_free_p above.   

References gcc_unreachable, gen_reload_chain_without_interm_reg_p(), 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_OTHER, reloads_unique_chain_p(), and rld.

Referenced by find_reg().

◆ reloads_unique_chain_p()

static bool reloads_unique_chain_p ( int r1,
int r2 )
static
Returns whether R1 and R2 are uniquely chained: the value of one
is used by the other, and that value is not used by any other
reload for this insn.  This is used to partially undo the decision
made in find_reloads when in the case of multiple
RELOAD_FOR_OPERAND_ADDRESS reloads it converts all
RELOAD_FOR_OPADDR_ADDR reloads into RELOAD_FOR_OPERAND_ADDRESS
reloads.  This code tries to avoid the conflict created by that
change.  It might be cleaner to explicitly keep track of which
RELOAD_FOR_OPADDR_ADDR reload is associated with which
RELOAD_FOR_OPERAND_ADDRESS reload, rather than to try to detect
this after the fact.  

References i, n_reloads, reg_mentioned_p(), rld, and rtx_equal_p().

Referenced by reloads_conflict().

◆ remove_init_insns()

static void remove_init_insns ( )
static
If a pseudo has no hard reg, delete the insns that made the equivalence.
If that insn didn't set the register (i.e., it copied the register to
memory), just delete that insn instead of the equivalencing insn plus
anything now dead.  If we call delete_dead_insn on that insn, we may
delete the insn that actually sets the register if the register dies
there and that is incorrect.   

References as_a(), can_throw_internal(), delete_dead_insn(), i, max_regno, NOTE_P, PATTERN(), reg_equiv_init, reg_renumber, reg_set_p(), regno_reg_rtx, SET_INSN_DELETED, and XEXP.

Referenced by reload().

◆ replace_pseudos_in()

static void replace_pseudos_in ( rtx * loc,
machine_mode mem_mode,
rtx usage )
static

◆ replaced_subreg()

static rtx replaced_subreg ( rtx x)
static
If X is not a subreg, return it unmodified.  If it is a subreg,
look up whether we made a replacement for the SUBREG_REG.  Return
either the replacement or the SUBREG_REG.   

References find_replacement(), GET_CODE, and SUBREG_REG.

Referenced by choose_reload_regs(), and gen_reload().

◆ scan_paradoxical_subregs()

static void scan_paradoxical_subregs ( rtx x)
static

◆ select_reload_regs()

static void select_reload_regs ( void )
static

References find_reload_regs(), and insns_need_reload.

Referenced by reload().

◆ set_initial_eh_label_offset()

static void set_initial_eh_label_offset ( rtx label)
static
Subroutine of set_initial_label_offsets called via for_each_eh_label.   

References NULL, and set_label_offsets().

Referenced by set_initial_label_offsets().

◆ set_initial_elim_offsets()

static void set_initial_elim_offsets ( void )
static

◆ set_initial_label_offsets()

static void set_initial_label_offsets ( void )
static
Initialize the known label offsets.
Set a known offset for each forced label to be at the initial offset
of each elimination.  We do this because we assume that all
computed jumps occur from a location where each elimination is
at its initial offset.
For all other labels, show that we don't know the offsets.   

References for_each_eh_label(), FOR_EACH_VEC_SAFE_ELT, forced_labels, i, rtx_insn_list::next(), nonlocal_goto_handler_labels, NULL, num_labels, offsets_known_at, set_initial_eh_label_offset(), and set_label_offsets().

Referenced by calculate_elim_costs_all_insns(), and reload().

◆ set_label_offsets()

static void set_label_offsets ( rtx x,
rtx_insn * insn,
int initial_p )
static
This function handles the tracking of elimination offsets around branches.

X is a piece of RTL being scanned.

INSN is the insn that it came from, if any.

INITIAL_P is nonzero if we are to set the offset to be the initial
offset and zero if we are setting the offset of the label to be the
current offset.   

References BARRIER_P, elim_table::can_eliminate, CODE_LABEL_NUMBER, first_label_num, GET_CODE, i, elim_table::initial_offset, label_ref_label(), LABEL_REF_NONLOCAL_P, NUM_ELIMINABLE_REGS, elim_table::offset, offsets_at, offsets_known_at, PATTERN(), pc_rtx, prev_nonnote_insn(), reg_eliminate, REG_NOTE_KIND, REG_NOTES, SET, SET_DEST, set_label_offsets(), set_offsets_for_label(), SET_SRC, XEXP, XVECEXP, and XVECLEN.

Referenced by calculate_elim_costs_all_insns(), calculate_needs_all_insns(), set_initial_eh_label_offset(), set_initial_label_offsets(), and set_label_offsets().

◆ set_offsets_for_label()

static void set_offsets_for_label ( rtx_insn * insn)
static

◆ set_reload_reg()

static int set_reload_reg ( int i,
int r )
static
I is the index in SPILL_REG_RTX of the reload register we are to allocate
for reload R.  If it's valid, get an rtx for it.  Return nonzero if
successful.   

References gen_rtx_REG(), GET_MODE, i, last_spill_reg, mark_reload_reg_in_use(), r, reload_spill_index, rld, spill_reg_rtx, spill_regs, targetm, and true_regnum().

Referenced by allocate_reload_reg(), and choose_reload_regs().

◆ spill_failure()

static void spill_failure ( rtx_insn * insn,
enum reg_class rclass )
static
Handle the failure to find a register to spill.
INSN should be one of the insns which needed this particular spill reg.   

References asm_noperands(), debug_reload_to_stream(), dump_file, error(), error_for_asm(), fatal_insn, INSN_UID(), PATTERN(), and reg_class_names.

Referenced by find_reload_regs().

◆ spill_hard_reg()

static void spill_hard_reg ( unsigned int regno,
int cant_eliminate )
static
Kick all pseudos out of hard register REGNO.

If CANT_ELIMINATE is nonzero, it means that we are doing this spill
because we found we can't eliminate some register.  In the case, no pseudos
are allowed to be in the register, even if they are only in a block that
doesn't require spill registers, unlike the case when we are spilling this
hard reg to produce another spill register.

Return nonzero if any pseudos needed to be kicked out.   

References bad_spill_regs_global, df_set_regs_ever_live(), end_hard_regno(), i, max_regno, PSEUDO_REGNO_MODE, reg_renumber, SET_HARD_REG_BIT, SET_REGNO_REG_SET, and spilled_pseudos.

◆ strip_paradoxical_subreg()

static bool strip_paradoxical_subreg ( rtx * op_ptr,
rtx * other_ptr )
static
*OP_PTR and *OTHER_PTR are two operands to a conceptual reload.
If *OP_PTR is a paradoxical subreg, try to remove that subreg
and apply the corresponding narrowing subreg to *OTHER_PTR.
Return true if the operands were changed, false otherwise.   

References gen_lowpart_common(), GET_CODE, GET_MODE, HARD_REGISTER_P, paradoxical_subreg_p(), REG_P, and SUBREG_REG.

Referenced by emit_output_reload_insns(), gen_reload(), and gen_reload_chain_without_interm_reg_p().

◆ substitute()

static void substitute ( rtx * where,
const_rtx what,
rtx repl )
static
The recursive function change all occurrences of WHAT in *WHERE
to REPL.   

References GET_CODE, GET_RTX_FORMAT, GET_RTX_LENGTH, i, rtx_equal_p(), substitute(), substitute_stack, XEXP, XVECEXP, and XVECLEN.

Referenced by gen_reload_chain_without_interm_reg_p(), and substitute().

◆ update_eliminable_offsets()

static void update_eliminable_offsets ( void )
static
Loop through all elimination pairs.
Recalculate the number not at initial offset.

Compute the maximum offset (minimum offset if the stack does not
grow downward) for each elimination pair.   

References elim_table::can_eliminate, elim_table::initial_offset, NUM_ELIMINABLE_REGS, num_not_at_initial_offset, elim_table::offset, elim_table::previous_offset, and reg_eliminate.

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

◆ update_eliminables()

static void update_eliminables ( HARD_REG_SET * pset)
static
See if anything that happened changes which eliminations are valid.
For example, on the SPARC, whether or not the frame pointer can
be eliminated can depend on what registers have been used.  We need
not check some conditions again (such as flag_omit_frame_pointer)
since they can't have changed.   

References elim_table::can_eliminate, elim_table::can_eliminate_previous, crtl, frame_pointer_needed, elim_table::from, HARD_FRAME_POINTER_REGNUM, num_eliminable, NUM_ELIMINABLE_REGS, reg_eliminate, SET_HARD_REG_BIT, SUPPORTS_STACK_ALIGNMENT, targetm, and elim_table::to.

Referenced by update_eliminables_and_spill().

◆ update_eliminables_and_spill()

static bool update_eliminables_and_spill ( void )
static
Call update_eliminables an spill any registers we can't eliminate anymore.
Return true iff a register was spilled.   

References CLEAR_HARD_REG_SET, i, spill_hard_reg, TEST_HARD_REG_BIT, update_eliminables(), and used_spill_regs.

Referenced by reload().

◆ verify_initial_elim_offsets()

static bool verify_initial_elim_offsets ( void )
static
Verify that the initial elimination offsets did not change since the
last call to set_initial_elim_offsets.  This is used to catch cases
where something illegal happened during reload_as_needed that could
cause incorrect code to be generated if we did not check for it.   

References elim_table::from, elim_table::initial_offset, num_eliminable, NUM_ELIMINABLE_REGS, reg_eliminate, targetm, and elim_table::to.

Referenced by reload().

◆ will_delete_init_insn_p()

static bool will_delete_init_insn_p ( rtx_insn * insn)
static
Return true if remove_init_insns will delete INSN.   

References can_throw_internal(), reg_equiv_init, REG_P, reg_renumber, REGNO, SET_DEST, single_set(), and XEXP.

Referenced by calculate_needs_all_insns(), and reload_as_needed().

Variable Documentation

◆ bad_spill_regs

HARD_REG_SET bad_spill_regs
static
This reg set indicates registers that can't be used as spill registers for
the currently processed insn.  These are the hard registers which are live
during the insn, but not allocated to pseudos, as well as fixed
registers.   

Referenced by find_reg(), ira_reassign_pseudos(), and order_regs_for_reload().

◆ bad_spill_regs_global

HARD_REG_SET bad_spill_regs_global
static
These are the hard registers that can't be used as spill register for any
insn.  This includes registers used for user variables and registers that
we can't eliminate.  A register that appears in this set also can't be used
to retry register allocation.   

Referenced by find_reg(), finish_spills(), reload(), and spill_hard_reg().

◆ caller_save_needed

int caller_save_needed
Flag set by local-alloc or global-alloc if anything is live in
a call-clobbered reg across calls.   

Referenced by allocno_reload_assign(), prepare_function_start(), reload(), and setup_reg_renumber().

◆ changed_allocation_pseudos

regset_head changed_allocation_pseudos
static
Record which pseudos changed their allocation in finish_spills.   

Referenced by finish_spills(), init_reload(), and reload().

◆ default_target_reload

struct target_reload default_target_reload
Reload pseudo regs into hard regs for insns that require hard regs.
   Copyright (C) 1987-2024 Free Software Foundation, Inc.

This file is part of GCC.

GCC 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 3, or (at your option) any later
version.

GCC 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 GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.   
This file contains the reload pass of the compiler, which is
run after register allocation has been done.  It checks that
each insn is valid (operands required to be in registers really
are in registers of the proper class) and fixes up invalid ones
by copying values temporarily into registers for the insns
that need them.

The results of register allocation are described by the vector
reg_renumber; the insns still contain pseudo regs, but reg_renumber
can be used to find which hard reg, if any, a pseudo reg is in.

The technique we always use is to free up a few hard regs that are
called ``reload regs'', and for each place where a pseudo reg
must be in a hard reg, copy it temporarily into one of the reload regs.

Reload regs are allocated locally for every instruction that needs
reloads.  When there are pseudos which are allocated to a register that
has been chosen as a reload reg, such pseudos must be ``spilled''.
This means that they go to other hard regs, or to stack slots if no other
available hard regs can be found.  Spilling can invalidate more
insns, requiring additional need for reloads, so we must keep checking
until the process stabilizes.

For machines with different classes of registers, we must keep track
of the register class needed for each reload, and make sure that
we allocate enough reload registers of each class.

The file reload.cc contains the code that checks one insn for
validity and reports the reloads that it needs.  This file
is in charge of scanning the entire rtl code, accumulating the
reload needs, spilling, assigning reload registers to use for
fixing up each insn, and generating the new insns to copy values
into the reload registers.   

◆ elim_bb

basic_block elim_bb
static
Global variables used by reload and its subroutines.   
The current basic block while in calculate_elim_costs_all_insns.   

Referenced by calculate_elim_costs_all_insns(), and note_reg_elim_costly().

◆ failure

◆ first_label_num

int first_label_num
static
For each label, we record the offset of each elimination.  If we reach
a label by more than one path and an offset differs, we cannot do the
elimination.  This information is indexed by the difference of the
number of the label and the first label number.  We can't offset the
pointer itself as this can cause problems on machines with segmented
memory.  The first table is an array of flags that records whether we
have yet encountered a label and the second table is an array of arrays,
one entry in the latter array for each elimination.   

Referenced by init_eliminable_invariants(), set_label_offsets(), and set_offsets_for_label().

◆ hard_regno_to_pseudo_regno

int hard_regno_to_pseudo_regno[FIRST_PSEUDO_REGISTER]
static
Map of hard regno to pseudo regno currently occupying the hard
reg.   

Referenced by count_pseudo(), count_spilled_pseudo(), find_reg(), and order_regs_for_reload().

◆ inpaddr_address_reload_insns

rtx_insn* inpaddr_address_reload_insns[MAX_RECOG_OPERANDS]
static

◆ input_address_reload_insns

rtx_insn* input_address_reload_insns[MAX_RECOG_OPERANDS]
static

◆ input_reload_insns

rtx_insn* input_reload_insns[MAX_RECOG_OPERANDS]
static
These arrays are filled by emit_reload_insns and its subroutines.   

Referenced by emit_input_reload_insns(), and emit_reload_insns().

◆ insns_need_reload

class insn_chain* insns_need_reload
static
List of all insns needing reloads.   

Referenced by calculate_needs_all_insns(), finish_spills(), reload(), and select_reload_regs().

◆ last_spill_reg

int last_spill_reg
static
Index of last register assigned as a spill register.  We allocate in
a round-robin fashion.   

Referenced by allocate_reload_reg(), reload(), and set_reload_reg().

◆ n_spills

int n_spills
static
Number of spill-regs so far; number of valid elements of spill_regs.   

Referenced by allocate_reload_reg(), choose_reload_regs(), finish_spills(), and reload().

◆ need_dce

bool need_dce
static
TRUE if we potentially left dead insns in the insn stream and want to
run DCE immediately after reload, FALSE otherwise.   

Referenced by delete_dead_insn(), do_reload(), and reload().

◆ new_spill_reg_store

rtx_insn* new_spill_reg_store[FIRST_PSEUDO_REGISTER]
static
Values to be put in spill_reg_store are put here first.  Instructions
must only be placed here if the associated reload register reaches
the end of the instruction's reload sequence.   

Referenced by emit_output_reload_insns(), and emit_reload_insns().

◆ num_eliminable

int num_eliminable
static

◆ num_eliminable_invariants

int num_eliminable_invariants
static
And the number of registers that are equivalent to a constant that
can be eliminated to frame_pointer / arg_pointer + constant.   

Referenced by calculate_elim_costs_all_insns(), calculate_needs_all_insns(), init_eliminable_invariants(), and reload_as_needed().

◆ num_labels

int num_labels
static
Number of labels in the current function.   

Referenced by init_eliminable_invariants(), and set_initial_label_offsets().

◆ num_not_at_initial_offset

int num_not_at_initial_offset
Record the number of pending eliminations that have an offset not equal
to their initial offset.  If nonzero, we use a new copy of each
replacement result in any insns encountered.   

Referenced by emit_input_reload_insns(), find_reloads(), find_reloads_address(), find_reloads_address_1(), find_reloads_toplev(), set_initial_elim_offsets(), set_offsets_for_label(), subst_reg_equivs(), and update_eliminable_offsets().

◆ offsets_at

◆ offsets_known_at

◆ operand_reload_insns

rtx_insn* operand_reload_insns = 0
static

◆ other_input_address_reload_insns

rtx_insn* other_input_address_reload_insns = 0
static

◆ other_input_reload_insns

rtx_insn* other_input_reload_insns = 0
static

◆ other_operand_reload_insns

rtx_insn* other_operand_reload_insns = 0
static

◆ other_output_reload_insns

rtx_insn* other_output_reload_insns[MAX_RECOG_OPERANDS]
static

◆ outaddr_address_reload_insns

rtx_insn* outaddr_address_reload_insns[MAX_RECOG_OPERANDS]
static

◆ output_address_reload_insns

rtx_insn* output_address_reload_insns[MAX_RECOG_OPERANDS]
static

◆ output_reload_insns

rtx_insn* output_reload_insns[MAX_RECOG_OPERANDS]
static

◆ pseudo_forbidden_regs

HARD_REG_SET* pseudo_forbidden_regs
static
This vector of reg sets indicates, for each pseudo, which hard
registers may not be used for retrying global allocation because they
are used as spill registers during one of the insns in which the
pseudo is live.   

Referenced by finish_spills(), ira_reassign_pseudos(), and reload().

◆ pseudo_previous_regs

HARD_REG_SET* pseudo_previous_regs
static
This vector of reg sets indicates, for each pseudo, which hard registers
may not be used for retrying global allocation because the register was
formerly spilled from one of them.  If we allowed reallocating a pseudo to
a register that it was already allocated to, reload might not
terminate.   

Referenced by finish_spills(), ira_reassign_pseudos(), and reload().

◆ pseudos_counted

regset_head pseudos_counted
static
Used for communication between order_regs_for_reload and count_pseudo.
Used to avoid counting one pseudo twice.   

Referenced by count_pseudo(), init_reload(), and order_regs_for_reload().

◆ reg_eliminate

◆ reg_eliminate_1

const struct elim_table_1 reg_eliminate_1[]
static
Initial value:
=
ELIMINABLE_REGS

Referenced by init_elim_table().

◆ reg_equivs

◆ reg_has_output_reload

regset_head reg_has_output_reload
static
Elt N nonzero if reg_last_reload_reg[N] has been set in this insn
for an output reload that stores into reg N.   

Referenced by choose_reload_regs(), emit_reload_insns(), forget_marked_reloads(), forget_old_reloads_1(), and reload_as_needed().

◆ reg_is_output_reload

HARD_REG_SET reg_is_output_reload
static
Indicates which hard regs are reload-registers for an output reload
in the current insn.   

Referenced by choose_reload_regs(), emit_output_reload_insns(), emit_reload_insns(), forget_marked_reloads(), forget_old_reloads_1(), and reload_as_needed().

◆ reg_last_reload_reg

rtx* reg_last_reload_reg
static
During reload_as_needed, element N contains a REG rtx for the hard reg
into which reg N has been reloaded (perhaps for a previous insn).   

Referenced by choose_reload_regs(), do_output_reload(), emit_reload_insns(), forget_marked_reloads(), forget_old_reloads_1(), inc_for_reload(), and reload_as_needed().

◆ reg_max_ref_mode

machine_mode* reg_max_ref_mode
static
Widest mode in which each pseudo reg is referred to (via subreg).   

Referenced by alter_reg(), init_eliminable_invariants(), ira_sort_regnos_for_alter_reg(), reload(), and scan_paradoxical_subregs().

◆ reg_old_renumber

short* reg_old_renumber
static
Vector to remember old contents of reg_renumber before spilling.   

Referenced by finish_spills(), and reload().

◆ reg_reloaded_contents

int reg_reloaded_contents[FIRST_PSEUDO_REGISTER]
static
During reload_as_needed, element N contains the last pseudo regno reloaded
into hard register N.  If that pseudo reg occupied more than one register,
reg_reloaded_contents points to that pseudo for each spill register in
use; all of these must remain set for an inheritance to occur.   

Referenced by choose_reload_regs(), delete_address_reloads_1(), do_input_reload(), do_output_reload(), emit_reload_insns(), and reload_as_needed().

◆ reg_reloaded_dead

HARD_REG_SET reg_reloaded_dead
static
Indicate if the register was dead at the end of the reload.
This is only valid if reg_reloaded_contents is set and valid.   

Referenced by choose_reload_regs(), and emit_reload_insns().

◆ reg_reloaded_died

HARD_REG_SET reg_reloaded_died
static

◆ reg_reloaded_insn

rtx_insn* reg_reloaded_insn[FIRST_PSEUDO_REGISTER]
static
During reload_as_needed, element N contains the insn for which
hard register N was last used.   Its contents are significant only
when reg_reloaded_valid is set for this register.   

Referenced by choose_reload_regs(), emit_reload_insns(), and reload_as_needed().

◆ reg_reloaded_valid

HARD_REG_SET reg_reloaded_valid
static
Indicate if reg_reloaded_insn / reg_reloaded_contents is valid.   

Referenced by choose_reload_regs(), do_input_reload(), do_output_reload(), emit_reload_insns(), forget_marked_reloads(), forget_old_reloads_1(), and reload_as_needed().

◆ reg_used_in_insn

HARD_REG_SET reg_used_in_insn
static
Records which hard regs are used in any way, either as explicit use or
by being allocated to a pseudo during any point of the current insn.   

Referenced by choose_reload_regs(), and choose_reload_regs_init().

◆ reload_first_uid

int reload_first_uid
First uid used by insns created by reload in this function.
Used in find_equiv_reg.   

Referenced by delete_address_reloads_1(), find_equiv_reg(), and reload().

◆ reload_firstobj

char* reload_firstobj
static
The point after all insn_chain structures.  Used to quickly deallocate
memory allocated in copy_reloads during calculate_needs_all_insns.   

Referenced by reload().

◆ reload_in_progress

int reload_in_progress = 0
Set to 1 while reload_as_needed is operating.
Required by some machines to handle any generated moves differently.   

Referenced by change_address_1(), constrain_operands(), emit_move_change_mode(), emit_move_complex_parts(), emit_move_multi_word(), gen_rtx_REG(), insn_invalid_p(), reload(), and verify_rtx_sharing().

◆ reload_inheritance_insn

rtx_insn* reload_inheritance_insn[MAX_RELOADS]
static
For an inherited reload, this is the insn the reload was inherited from,
if we know it.  Otherwise, this is 0.   

Referenced by choose_reload_regs(), and choose_reload_regs_init().

◆ reload_inherited

char reload_inherited[MAX_RELOADS]
static
Indexed by reload number, 1 if incoming value
inherited from previous insns.   

Referenced by choose_reload_regs(), choose_reload_regs_init(), delete_address_reloads_1(), delete_output_reload(), do_input_reload(), emit_input_reload_insns(), and emit_reload_insns().

◆ reload_insn_chain

class insn_chain* reload_insn_chain

◆ reload_insn_firstobj

char* reload_insn_firstobj
static
This points before all local rtl generated by register elimination.
Used to quickly free all memory after processing one insn.   

Referenced by calculate_needs_all_insns(), and copy_reloads().

◆ reload_obstack

struct obstack reload_obstack
static
This obstack is used for allocation of rtl during register elimination.
The allocated storage can be freed once find_reloads has processed the
insn.   

Referenced by calculate_needs_all_insns(), copy_reloads(), init_reload(), new_insn_chain(), and reload().

◆ reload_order

short reload_order[MAX_RELOADS]
static
Vector of reload-numbers showing the order in which the reloads should
be processed.   

Referenced by choose_reload_regs(), emit_reload_insns(), find_reg(), and find_reload_regs().

◆ reload_override_in

rtx reload_override_in[MAX_RELOADS]
static
If nonzero, this is a place to get the value of the reload,
rather than using reload_in.   

Referenced by choose_reload_regs(), choose_reload_regs_init(), conflicts_with_override(), delete_address_reloads_1(), delete_output_reload(), do_input_reload(), emit_input_reload_insns(), and emit_reload_insns().

◆ reload_reg_rtx_for_input

rtx reload_reg_rtx_for_input[MAX_RELOADS]
static
Index X is the value of rld[X].reg_rtx, adjusted for the input mode.   

Referenced by do_input_reload(), emit_input_reload_insns(), and emit_reload_insns().

◆ reload_reg_rtx_for_output

rtx reload_reg_rtx_for_output[MAX_RELOADS]
static
Index X is the value of rld[X].reg_rtx, adjusted for the output mode.   

Referenced by do_output_reload(), emit_output_reload_insns(), and emit_reload_insns().

◆ reload_reg_unavailable

HARD_REG_SET reload_reg_unavailable
static
The following HARD_REG_SETs indicate when each hard register is
used for a reload of various parts of the current insn.   
If reg is unavailable for all reloads.   

Referenced by choose_reload_regs(), choose_reload_regs_init(), reload_reg_free_for_value_p(), and reload_reg_free_p().

◆ reload_reg_used

HARD_REG_SET reload_reg_used
static

◆ reload_reg_used_at_all

HARD_REG_SET reload_reg_used_at_all
static
If reg is in use as a reload reg for any sort of reload.   

Referenced by allocate_reload_reg(), choose_reload_regs(), choose_reload_regs_init(), and mark_reload_reg_in_use().

◆ reload_reg_used_for_inherit

HARD_REG_SET reload_reg_used_for_inherit
static
If reg is use as an inherited reload.  We just mark the first register
in the group.   

Referenced by allocate_reload_reg(), choose_reload_regs(), and choose_reload_regs_init().

◆ reload_reg_used_in_inpaddr_addr

HARD_REG_SET reload_reg_used_in_inpaddr_addr[MAX_RECOG_OPERANDS]
static
If reg is in use for a RELOAD_FOR_INPADDR_ADDRESS reload for operand I.   

Referenced by choose_reload_regs_init(), clear_reload_reg_in_use(), mark_reload_reg_in_use(), reload_reg_free_p(), and reload_reg_reaches_end_p().

◆ reload_reg_used_in_input

HARD_REG_SET reload_reg_used_in_input[MAX_RECOG_OPERANDS]
static
If reg is in use for a RELOAD_FOR_INPUT reload for operand I.   

Referenced by choose_reload_regs_init(), clear_reload_reg_in_use(), mark_reload_reg_in_use(), reload_reg_free_p(), and reload_reg_reaches_end_p().

◆ reload_reg_used_in_input_addr

HARD_REG_SET reload_reg_used_in_input_addr[MAX_RECOG_OPERANDS]
static
If reg is in use for a RELOAD_FOR_INPUT_ADDRESS reload for operand I.   

Referenced by choose_reload_regs_init(), clear_reload_reg_in_use(), mark_reload_reg_in_use(), reload_reg_free_p(), and reload_reg_reaches_end_p().

◆ reload_reg_used_in_insn

HARD_REG_SET reload_reg_used_in_insn
static

◆ reload_reg_used_in_op_addr

HARD_REG_SET reload_reg_used_in_op_addr
static
If reg is in use for a RELOAD_FOR_OPERAND_ADDRESS reload.   

Referenced by choose_reload_regs_init(), clear_reload_reg_in_use(), mark_reload_reg_in_use(), reload_reg_free_p(), and reload_reg_reaches_end_p().

◆ reload_reg_used_in_op_addr_reload

HARD_REG_SET reload_reg_used_in_op_addr_reload
static
If reg is in use for a RELOAD_FOR_OPADDR_ADDR reload.   

Referenced by choose_reload_regs_init(), clear_reload_reg_in_use(), mark_reload_reg_in_use(), reload_reg_free_p(), and reload_reg_reaches_end_p().

◆ reload_reg_used_in_other_addr

HARD_REG_SET reload_reg_used_in_other_addr
static
If reg is in use for a RELOAD_FOR_OTHER_ADDRESS reload.   

Referenced by choose_reload_regs_init(), clear_reload_reg_in_use(), mark_reload_reg_in_use(), and reload_reg_free_p().

◆ reload_reg_used_in_outaddr_addr

HARD_REG_SET reload_reg_used_in_outaddr_addr[MAX_RECOG_OPERANDS]
static
If reg is in use for a RELOAD_FOR_OUTADDR_ADDRESS reload for operand I.   

Referenced by choose_reload_regs_init(), clear_reload_reg_in_use(), mark_reload_reg_in_use(), reload_reg_free_p(), and reload_reg_reaches_end_p().

◆ reload_reg_used_in_output

HARD_REG_SET reload_reg_used_in_output[MAX_RECOG_OPERANDS]
static
If reg is in use for a RELOAD_FOR_OUTPUT reload for operand I.   

Referenced by choose_reload_regs_init(), clear_reload_reg_in_use(), mark_reload_reg_in_use(), reload_reg_free_p(), and reload_reg_reaches_end_p().

◆ reload_reg_used_in_output_addr

HARD_REG_SET reload_reg_used_in_output_addr[MAX_RECOG_OPERANDS]
static
If reg is in use for a RELOAD_FOR_OUTPUT_ADDRESS reload for operand I.   

Referenced by choose_reload_regs_init(), clear_reload_reg_in_use(), mark_reload_reg_in_use(), reload_reg_free_p(), and reload_reg_reaches_end_p().

◆ reload_spill_index

int reload_spill_index[MAX_RELOADS]
static
For each reload, the hard register number of the register used,
or -1 if we did not need a register for this reload.   

Referenced by choose_reload_regs(), deallocate_reload_reg(), do_input_reload(), emit_output_reload_insns(), emit_reload_insns(), and set_reload_reg().

◆ reload_startobj

char* reload_startobj
static
Points to the beginning of the reload_obstack.  All insn_chain structures
are allocated first.   

Referenced by init_reload(), and reload().

◆ something_needs_elimination

int something_needs_elimination
static
Set during calculate_needs if an insn needs register elimination.   

Referenced by calculate_needs_all_insns(), and reload().

◆ something_needs_operands_changed

int something_needs_operands_changed
static
Set during calculate_needs if an insn needs an operand changed.   

Referenced by calculate_needs_all_insns(), and reload().

◆ something_was_spilled

bool something_was_spilled
static
Set by alter_regs if we spilled a register to the stack.   

Referenced by alter_reg(), and reload().

◆ spill_add_cost

int spill_add_cost[FIRST_PSEUDO_REGISTER]
static
When spilling multiple hard registers, we use SPILL_COST for the first
spilled hard reg and SPILL_ADD_COST for subsequent regs.  SPILL_ADD_COST
only the first hard reg for a multi-reg pseudo.   

Referenced by count_pseudo(), count_spilled_pseudo(), find_reg(), and order_regs_for_reload().

◆ spill_cost

◆ spill_reg_order

short spill_reg_order[FIRST_PSEUDO_REGISTER]
static
This table is the inverse mapping of spill_regs:
indexed by hard reg number,
it contains the position of that reg in spill_regs,
or -1 for something that is not in spill_regs.

?!?  This is no longer accurate.   

Referenced by allocate_reload_reg(), calculate_needs_all_insns(), choose_reload_regs(), deallocate_reload_reg(), delete_address_reloads_1(), finish_spills(), and reload_as_needed().

◆ spill_reg_rtx

rtx spill_reg_rtx[FIRST_PSEUDO_REGISTER]
static
In parallel with spill_regs, contains REG rtx's for those regs.
Holds the last rtx used for any given reg, or 0 if it has never
been used for spilling yet.  This rtx is reused, provided it has
the proper mode.   

Referenced by reload_as_needed(), and set_reload_reg().

◆ spill_reg_store

rtx_insn* spill_reg_store[FIRST_PSEUDO_REGISTER]
static
In parallel with spill_regs, contains nonzero for a spill reg
that was stored after the last time it was used.
The precise value is the insn generated to do the store.   

Referenced by choose_reload_regs(), delete_output_reload(), do_input_reload(), do_output_reload(), emit_input_reload_insns(), emit_reload_insns(), forget_marked_reloads(), forget_old_reloads_1(), and reload_as_needed().

◆ spill_reg_stored_to

rtx spill_reg_stored_to[FIRST_PSEUDO_REGISTER]
static
This is the register that was stored with spill_reg_store.  This is a
copy of reload_out / reload_out_reg when the value was stored; if
reload_out is a MEM, spill_reg_stored_to will be set to reload_out_reg.   

Referenced by delete_output_reload(), do_input_reload(), do_output_reload(), emit_input_reload_insns(), and emit_reload_insns().

◆ spill_regs

short spill_regs[FIRST_PSEUDO_REGISTER]
static
Describes order of use of registers for reloading
of spilled pseudo-registers.  `n_spills' is the number of
elements that are actually valid; new ones are added at the end.

Both spill_regs and spill_reg_order are used on two occasions:
once during find_reload_regs, where they keep track of the spill registers
for a single insn, but also during reload_as_needed where they show all
the registers ever used by reload.  For the latter case, the information
is calculated during finish_spills.   

Referenced by allocate_reload_reg(), choose_reload_regs(), finish_spills(), reload(), and set_reload_reg().

◆ spill_stack_slot

rtx spill_stack_slot[FIRST_PSEUDO_REGISTER]
static
Record the stack slot for each spilled hard register.   

Referenced by alter_reg(), and reload().

◆ spill_stack_slot_width

poly_uint64 spill_stack_slot_width[FIRST_PSEUDO_REGISTER]
static
Width allocated so far for that stack slot.   

Referenced by alter_reg(), and reload().

◆ spilled_pseudos

◆ substitute_stack

vec<rtx_p> substitute_stack
static

◆ temp_pseudo_reg_arr

int* temp_pseudo_reg_arr
static
Temporary array of pseudo-register number.   

Referenced by finish_spills(), and reload().

◆ unused_insn_chains

class insn_chain* unused_insn_chains = 0
static
List of insn chains that are currently unused.   

Referenced by calculate_needs_all_insns(), delete_caller_save_insns(), new_insn_chain(), and reload().

◆ used_spill_regs

HARD_REG_SET used_spill_regs
static
All hard regs that have been used as spill registers for any insn are
marked in this set.   

Referenced by find_reload_regs(), finish_spills(), reload(), and update_eliminables_and_spill().

◆ used_spill_regs_local

HARD_REG_SET used_spill_regs_local
static
This is used to keep track of the spill regs used in one insn.   

Referenced by find_reg(), and find_reload_regs().