GCC Middle and Back End API 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"
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 rtx * | rtx_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_insn * | gen_reload (rtx, rtx, int, enum reload_type) |
static rtx_insn * | emit_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_insn * | emit_insn_if_valid_for_reload_1 (rtx pat) |
#define NUM_ELIMINABLE_REGS ARRAY_SIZE (reg_eliminate_1) |
Referenced by check_eliminable_occurrences(), eliminate_regs_1(), eliminate_regs_in_insn(), elimination_costs_in_insn(), elimination_effects(), elimination_target_reg_p(), init_elim_table(), init_eliminable_invariants(), mark_not_eliminable(), reload(), set_initial_elim_offsets(), set_label_offsets(), set_offsets_for_label(), update_eliminable_offsets(), update_eliminables(), and verify_initial_elim_offsets().
#define spill_indirect_levels (this_target_reload->x_spill_indirect_levels) |
Referenced by calculate_needs_all_insns(), init_reload(), and reload_as_needed().
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.
|
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().
|
static |
Modify the home of pseudo-reg I. The new home is present in reg_renumber[I]. FROM_REG may be the hard reg that the pseudo-reg is being spilled from; or it may be -1, meaning there is none or it is not relevant. This is used so that all pseudos spilled from a given hard reg can share one stack slot.
References adjust_address_nv, assign_stack_local(), opt_mode< T >::else_blk(), gcc_checking_assert, GET_MODE, GET_MODE_ALIGNMENT, GET_MODE_BITSIZE(), GET_MODE_SIZE(), i, int_mode_for_size(), ira_conflicts_p, ira_mark_new_stack_slot(), ira_reuse_stack_slot(), known_ge, maybe_gt, MEM_ALIGN, min_align(), NULL_RTX, partial_subreg_p(), reg_equiv_constant, reg_equiv_init, reg_equiv_invariant, reg_equiv_memory_loc, reg_max_ref_mode, REG_N_REFS(), REG_P, reg_renumber, regno_reg_rtx, set_mem_attrs_for_spill(), SET_REGNO, SET_REGNO_REG_SET, something_was_spilled, spill_stack_slot, spill_stack_slot_width, spilled_pseudos, subreg_size_lowpart_offset(), and wider_subreg_mode().
Referenced by delete_output_reload(), eliminate_regs_1(), emit_input_reload_insns(), finish_spills(), and reload().
void calculate_elim_costs_all_insns | ( | void | ) |
This function is called from the register allocator to set up estimates for the cost of eliminating pseudos which have REG_EQUIV equivalences to an invariant. The structure is similar to calculate_needs_all_insns.
References cfun, dump_file, elim_bb, eliminate_regs_1(), elimination_costs_in_insn(), FOR_BB_INSNS, FOR_EACH_BB_FN, free(), get_insns(), GET_MODE, i, init_elim_table(), init_eliminable_invariants(), INSN_P, ira_adjust_equiv_reg_cost(), JUMP_P, JUMP_TABLE_DATA_P, LABEL_P, max_regno, NULL, num_eliminable, num_eliminable_invariants, offsets_at, offsets_known_at, optimize_bb_for_speed_p(), reg_equiv_constant, reg_equiv_init, reg_equiv_invariant, REG_FREQ_FROM_BB, REG_NOTES, REG_P, reg_renumber, REGNO, SET_DEST, set_initial_elim_offsets(), set_initial_label_offsets(), set_label_offsets(), SET_SRC, set_src_cost(), single_set(), and update_eliminable_offsets().
Referenced by ira_costs().
|
static |
Walk the chain of insns, and determine for each whether it needs reloads and/or eliminations. Build the corresponding insns_need_reload list, and set something_needs_elimination as appropriate.
References copy_reloads(), delete_insn(), eliminate_regs_in_insn(), find_reloads(), INSN_CODE, INSN_P, insns_need_reload, ira_conflicts_p, ira_mark_memory_move_deletion(), JUMP_P, JUMP_TABLE_DATA_P, LABEL_P, n_reloads, NULL, num_eliminable, num_eliminable_invariants, PATTERN(), reg_equiv_memory_loc, REG_NOTES, REG_P, reg_renumber, REGNO, reload_insn_chain, reload_insn_firstobj, reload_obstack, rtx_equal_p(), SET_DEST, set_label_offsets(), SET_SRC, single_set(), something_needs_elimination, something_needs_operands_changed, spill_indirect_levels, spill_reg_order, unused_insn_chains, update_eliminable_offsets(), and will_delete_init_insn_p().
Referenced by reload().
|
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().
|
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().
|
static |
Initialize all the tables needed to allocate reload registers. CHAIN is the insn currently being processed; SAVE_RELOAD_REG_RTX is the array we use to restore the reg_rtx field for every reload.
References CLEAR_HARD_REG_SET, compute_use_by_pseudos(), i, mark_reload_reg_in_use(), MAX_RELOADS, n_reloads, REG_SET_TO_HARD_REG_SET, reg_used_in_insn, REGNO, reload_inheritance_insn, reload_inherited, reload_n_operands, reload_override_in, reload_reg_unavailable, reload_reg_used, reload_reg_used_at_all, reload_reg_used_for_inherit, reload_reg_used_in_inpaddr_addr, reload_reg_used_in_input, reload_reg_used_in_input_addr, reload_reg_used_in_insn, reload_reg_used_in_op_addr, reload_reg_used_in_op_addr_reload, reload_reg_used_in_other_addr, reload_reg_used_in_outaddr_addr, reload_reg_used_in_output, reload_reg_used_in_output_addr, and rld.
Referenced by choose_reload_regs().
|
static |
Similarly, but show REGNO is no longer in use for a reload.
References CLEAR_HARD_REG_BIT, end_hard_regno(), gcc_unreachable, hard_regno_nregs(), i, n_reloads, r, 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_used, reload_reg_used_in_inpaddr_addr, reload_reg_used_in_input, reload_reg_used_in_input_addr, reload_reg_used_in_insn, reload_reg_used_in_op_addr, reload_reg_used_in_op_addr_reload, reload_reg_used_in_other_addr, reload_reg_used_in_outaddr_addr, reload_reg_used_in_output, reload_reg_used_in_output_addr, rld, and true_regnum().
Referenced by choose_reload_regs(), and deallocate_reload_reg().
|
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().
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().
|
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().
|
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().
|
static |
Update the spill cost arrays, considering that pseudo REG is live.
References gcc_assert, hard_regno_nregs(), hard_regno_to_pseudo_regno, ira_conflicts_p, PSEUDO_REGNO_MODE, pseudos_counted, r, REG_FREQ, reg_renumber, REGNO_REG_SET_P, SET_REGNO_REG_SET, spill_add_cost, spill_cost, and spilled_pseudos.
Referenced by order_regs_for_reload().
|
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().
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().
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().
|
static |
Subfunction of delete_address_reloads: process registers found in X.
References delete_address_reloads_1(), delete_insn(), GET_CODE, GET_RTX_FORMAT, GET_RTX_LENGTH, i, i2, INSN_P, INSN_UID(), JUMP_P, LABEL_P, n_reloads, NEXT_INSN(), PATTERN(), PREV_INSN(), REG_P, reg_referenced_p(), reg_reloaded_contents, reg_set_p(), REGNO, reload_first_uid, reload_inherited, reload_override_in, rld, rtx_equal_p(), SET_DEST, SET_SRC, single_set(), spill_reg_order, XEXP, XVECEXP, and XVECLEN.
Referenced by delete_address_reloads(), and delete_address_reloads_1().
|
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().
|
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().
|
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().
|
static |
Do input reloading for reload RL, which is for the insn described by CHAIN and has the number J.
References dead_or_set_p(), delete_output_reload(), emit_input_reload_insns(), GET_MODE, HARD_REGISTER_P, MEM_P, REG_P, reg_reloaded_contents, reg_reloaded_valid, REGNO, regno_reg_rtx, reload_adjust_reg_for_mode(), reload_inherited, reload_override_in, reload_reg_rtx_for_input, reload_spill_index, rld, rtx_equal_p(), spill_reg_store, spill_reg_stored_to, and TEST_HARD_REG_BIT.
Referenced by emit_reload_insns().
|
static |
Do output reloading for reload RL, which is for the insn described by CHAIN and has the number J. ??? At some point we need to support handling output reloads of JUMP_INSNs.
References asm_noperands(), delete_output_reload(), emit_output_reload_insns(), error_for_asm(), fatal_insn, find_reg_note(), gcc_assert, gen_lowpart_common(), gen_rtx_REG(), GET_CODE, GET_MODE, NONJUMP_INSN_P, PATTERN(), reg_last_reload_reg, REG_P, reg_reloaded_contents, reg_reloaded_valid, REGNO, reload_adjust_reg_for_mode(), reload_reg_rtx_for_output, rld, rtx_equal_p(), spill_reg_store, spill_reg_stored_to, SUBREG_REG, TEST_HARD_REG_BIT, word_mode, and XEXP.
Referenced by emit_reload_insns().
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().
|
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().
|
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().
|
static |
Like eliminate_regs_in_insn, but only estimate costs for the use of the register allocator. INSN is the instruction we need to examine, we perform eliminations in its operands and record cases where eliminating a reg with an invariant equivalence would add extra cost.
References asm_noperands(), elim_table::can_eliminate, check_eliminable_occurrences(), CONST_INT_P, DEBUG_INSN_P, recog_data_d::dup_loc, recog_data_d::dup_num, eliminate_regs_1(), elimination_effects(), extract_insn(), elim_table::from_rtx, gcc_assert, GET_CODE, i, insn_data, recog_data_d::n_dups, n_operands, recog_data_d::n_operands, note_reg_elim_costly(), NULL_RTX, NUM_ELIMINABLE_REGS, elim_table::offset, OP_IN, recog_data_d::operand, recog_data_d::operand_loc, recog_data_d::operand_type, PATTERN(), elim_table::previous_offset, recog_data, recog_memoized(), elim_table::ref_outside_mem, reg_eliminate, REG_NOTE_KIND, REG_NOTES, REG_P, REGNO, SET_DEST, SET_SRC, single_set(), and XEXP.
Referenced by calculate_elim_costs_all_insns().
|
static |
Scan rtx X for modifications of elimination target registers. Update the table of eliminables to reflect the changed state. MEM_MODE is the mode of an enclosing MEM rtx, or VOIDmode if not within a MEM.
References elim_table::can_eliminate, CASE_CONST_ANY, CONST_INT_P, elimination_effects(), elim_table::from_rtx, function_invariant_p(), gcc_fallthrough, GET_CODE, GET_MODE, GET_MODE_SIZE(), GET_RTX_FORMAT, GET_RTX_LENGTH, hard_frame_pointer_rtx, i, INTVAL, NUM_ELIMINABLE_REGS, elim_table::offset, paradoxical_subreg_p(), elim_table::ref_outside_mem, reg_eliminate, reg_equiv_constant, reg_equiv_memory_loc, reg_equivs, REG_P, reg_renumber, REGNO, SET, SET_DEST, SET_SRC, stack_pointer_rtx, SUBREG_REG, elim_table::to_rtx, XEXP, XVECEXP, and XVECLEN.
Referenced by eliminate_regs_in_insn(), elimination_costs_in_insn(), and elimination_effects().
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().
|
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().
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().
Helper for emit_insn_if_valid_for_reload.
References constrain_operands(), delete_insns_since(), emit_insn(), extract_insn(), get_enabled_alternatives(), get_last_insn(), last, NULL, and recog_memoized().
Referenced by emit_insn_if_valid_for_reload().
|
static |
Generate insns to for the output reload RL, which is for the insn described by CHAIN and has the number J.
References cfun, copy_reg_eh_region_note_forward(), emit_insn(), end_sequence(), find_regno_note(), forget_old_reloads_1(), gcc_assert, gen_reload(), get_insns(), GET_MODE, HARD_REGISTER_P, INSN_P, rtx_def::mode, new_spill_reg_store, NEXT_INSN(), note_stores(), NULL, NULL_RTX, other_output_reload_insns, output_reload_insns, PATTERN(), push_to_sequence(), reg_equiv_mem, reg_is_output_reload, reg_mentioned_p(), REG_P, reg_reloaded_died, REGNO, regno_clobbered_p(), reload_adjust_reg_for_mode(), RELOAD_OTHER, reload_reg_rtx_for_output, reload_reg_rtx_reaches_end_p(), reload_spill_index, rld, rtx_equal_p(), secondary_reload_class(), SET_DEST, SET_HARD_REG_BIT, SET_SRC, single_set(), start_sequence(), and strip_paradoxical_subreg().
Referenced by do_output_reload().
|
static |
Output insns to reload values in and out of the chosen reload regs.
AUTO_INC
References CLEAR_HARD_REG_BIT, CLEAR_HARD_REG_SET, debug_reload_to_stream(), do_input_reload(), do_output_reload(), dump_file, emit_insn_after(), emit_insn_before(), END_REGNO(), find_regno_note(), forget_old_reloads_1(), gcc_assert, GET_CODE, GET_MODE, HARD_REGISTER_NUM_P, HARD_REGISTER_P, hard_regno_nregs(), i, inherit_piecemeal_p(), inpaddr_address_reload_insns, input_address_reload_insns, input_reload_insns, INSN_UID(), MEM_P, n_reloads, new_spill_reg_store, nr, NULL, NULL_RTX, operand_reload_insns, other_input_address_reload_insns, other_input_reload_insns, other_operand_reload_insns, other_output_reload_insns, outaddr_address_reload_insns, output_address_reload_insns, output_reload_insns, PATTERN(), r, reg_has_output_reload, reg_is_output_reload, reg_last_reload_reg, REG_NREGS, REG_P, reg_reloaded_contents, reg_reloaded_dead, reg_reloaded_died, reg_reloaded_insn, reg_reloaded_valid, reg_set_p(), REGNO, regno_reg_rtx, REGNO_REG_SET_P, reload_inherited, reload_n_operands, reload_order, reload_override_in, reload_reg_reaches_end_p(), reload_reg_rtx_for_input, reload_reg_rtx_for_output, reload_reg_rtx_reaches_end_p(), reload_spill_index, rld, SET_DEST, SET_HARD_REG_BIT, SET_REGNO_REG_SET, SET_SRC, single_set(), spill_reg_store, spill_reg_stored_to, SUBREG_REG, and XEXP.
Referenced by reload_as_needed().
|
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().
|
static |
Find reload register to use for reload number ORDER.
References bad_spill_regs, bad_spill_regs_global, CLEAR_HARD_REG_SET, count_spilled_pseudo(), crtl, dump_file, EXECUTE_IF_SET_IN_REG_SET, gcc_assert, hard_regno_nregs(), hard_regno_to_pseudo_regno, i, INT_MAX, inv_reg_alloc_order, ira_better_spill_reload_regno_p(), ira_conflicts_p, r, reg_alloc_order, REG_P, REGNO, reload(), reload_order, reloads_conflict(), rld, SET_HARD_REG_BIT, spill_add_cost, spill_cost, targetm, TEST_HARD_REG_BIT, and used_spill_regs_local.
Referenced by find_reload_regs().
|
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().
|
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().
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().
|
static |
Forget the reloads marked in regset by previous function.
References CLEAR_HARD_REG_BIT, EXECUTE_IF_SET_IN_REG_SET, n_reloads, reg_has_output_reload, reg_is_output_reload, reg_last_reload_reg, reg_reloaded_valid, REGNO_REG_SET_P, spill_reg_store, and TEST_HARD_REG_BIT.
Referenced by reload_as_needed().
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().
|
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().
|
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().
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().
|
static |
Emit code to perform a reload from IN (which may be a reload register) to OUT (which may also be a reload register). IN or OUT is from operand OPNUM with reload type TYPE. Returns first insn emitted.
References CONSTANT_P, emit_insn(), emit_insn_if_valid_for_reload(), fatal_insn, find_replacement(), gcc_assert, gen_add2_insn(), gen_move_insn(), gen_reload(), gen_rtx_REG(), GET_CODE, get_insns(), get_last_insn(), GET_MODE, get_secondary_mem(), insn_operand_matches(), last, mark_jump_label(), MEM_P, NEXT_INSN(), OBJECT_P, optab_handler(), reg_or_subregno(), reg_overlap_mentioned_p(), REG_P, REGNO, replaced_subreg(), rtx_equal_p(), set_dst_reg_note(), set_unique_reg_note(), strip_paradoxical_subreg(), targetm, UNARY_P, and XEXP.
Referenced by emit_input_reload_insns(), emit_output_reload_insns(), and gen_reload().
|
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().
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().
|
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().
|
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().
|
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().
|
static |
Initialize the table of registers to eliminate. Pre-condition: global flag frame_pointer_needed has been set before calling this function.
References elim_table::can_eliminate, elim_table::can_eliminate_previous, frame_pointer_needed, elim_table::from, elim_table_1::from, elim_table::from_rtx, gen_rtx_REG(), num_eliminable, NUM_ELIMINABLE_REGS, reg_eliminate, reg_eliminate_1, stack_realign_fp, SUPPORTS_STACK_ALIGNMENT, targetm, elim_table::to, elim_table_1::to, and elim_table::to_rtx.
Referenced by calculate_elim_costs_all_insns(), and reload().
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().
void init_reload | ( | void | ) |
Initialize the reload pass. This is called at the beginning of compilation and may be called again if the target is reinitialized.
References changed_allocation_pseudos, double_reg_address_ok, gcc_obstack_init, gen_int_mode(), gen_rtx_MEM(), gen_rtx_REG(), HARD_FRAME_POINTER_REGNUM, i, indirect_symref_ok, INIT_REG_SET, LAST_VIRTUAL_REGISTER, memory_address_p, NULL, plus_constant(), pseudos_counted, reload_obstack, reload_startobj, spill_indirect_levels, and spilled_pseudos.
Referenced by backend_init_target().
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().
|
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().
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().
|
static |
Mark reg REGNO as in use for a reload of the sort spec'd by OPNUM and TYPE. MODE is used to indicate how many consecutive regs are actually used.
References add_to_hard_reg_set(), 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_used, reload_reg_used_at_all, reload_reg_used_in_inpaddr_addr, reload_reg_used_in_input, reload_reg_used_in_input_addr, reload_reg_used_in_insn, reload_reg_used_in_op_addr, reload_reg_used_in_op_addr_reload, reload_reg_used_in_other_addr, reload_reg_used_in_outaddr_addr, reload_reg_used_in_output, and reload_reg_used_in_output_addr.
Referenced by choose_reload_regs(), choose_reload_regs_init(), and set_reload_reg().
|
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().
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().
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().
|
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().
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().
|
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().
|
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().
|
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().
|
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().
|
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().
|
static |
1 if reg REGNO is free as a reload reg for a reload of the sort specified by OPNUM and TYPE.
References gcc_unreachable, i, 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, reload_reg_unavailable, reload_reg_used, reload_reg_used_in_inpaddr_addr, reload_reg_used_in_input, reload_reg_used_in_input_addr, reload_reg_used_in_insn, reload_reg_used_in_op_addr, reload_reg_used_in_op_addr_reload, reload_reg_used_in_other_addr, reload_reg_used_in_outaddr_addr, reload_reg_used_in_output, reload_reg_used_in_output_addr, and TEST_HARD_REG_BIT.
Referenced by allocate_reload_reg().
|
static |
Return 1 if the value in reload reg REGNO, as used by the reload with the number RELOADNUM, is still available in REGNO at the end of the insn. We can assume that the reload reg was already tested for availability at the time it is needed, and we should not check this again, in case the reg has already been marked in use.
References END_REGNO(), gcc_unreachable, i, n_reloads, NULL_RTX, REGNO, 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, reload_reg_used, reload_reg_used_in_inpaddr_addr, reload_reg_used_in_input, reload_reg_used_in_input_addr, reload_reg_used_in_insn, reload_reg_used_in_op_addr, reload_reg_used_in_op_addr_reload, reload_reg_used_in_outaddr_addr, reload_reg_used_in_output, reload_reg_used_in_output_addr, rld, and TEST_HARD_REG_BIT.
Referenced by emit_reload_insns(), and reload_reg_rtx_reaches_end_p().
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().
|
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().
|
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().
|
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 all pseudos found in LOC with their corresponding equivalences.
References eliminate_regs_1(), gcc_assert, gen_rtx_MEM(), GET_CODE, GET_MODE, GET_RTX_FORMAT, GET_RTX_LENGTH, i, reg_equiv_address, reg_equiv_constant, reg_equiv_invariant, reg_equiv_mem, REG_P, REGNO, regno_reg_rtx, replace_pseudos_in(), usage(), XEXP, XVECEXP, and XVECLEN.
Referenced by reload(), and replace_pseudos_in().
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().
|
static |
Find all paradoxical subregs within X and update reg_max_ref_mode.
References CASE_CONST_ANY, GET_CODE, GET_MODE, GET_RTX_FORMAT, GET_RTX_LENGTH, i, mark_home_live_1(), partial_subreg_p(), reg_max_ref_mode, REG_P, REGNO, scan_paradoxical_subregs(), SUBREG_REG, XEXP, XVECEXP, and XVECLEN.
Referenced by init_eliminable_invariants(), and scan_paradoxical_subregs().
|
static |
References find_reload_regs(), and insns_need_reload.
Referenced by reload().
|
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().
|
static |
Reset all offsets on eliminable registers to their initial values.
References elim_table::from, elim_table::initial_offset, NUM_ELIMINABLE_REGS, num_not_at_initial_offset, elim_table::offset, elim_table::previous_offset, reg_eliminate, targetm, and elim_table::to.
Referenced by calculate_elim_costs_all_insns(), reload(), and reload_as_needed().
|
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().
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, 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().
|
static |
Set all elimination offsets to the known values for the code label given by INSN.
References elim_table::can_eliminate, CODE_LABEL_NUMBER, first_label_num, i, elim_table::initial_offset, NUM_ELIMINABLE_REGS, num_not_at_initial_offset, elim_table::offset, offsets_at, elim_table::previous_offset, and reg_eliminate.
Referenced by reload_as_needed(), and set_label_offsets().
|
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().
|
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().
|
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.
*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().
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().
|
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().
|
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().
|
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().
|
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().
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().
|
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().
|
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().
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().
|
static |
Record which pseudos changed their allocation in finish_spills.
Referenced by finish_spills(), init_reload(), and 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.
|
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().
|
static |
Nonzero means we couldn't get enough spill regs.
Referenced by check_unique_operand_names(), expand_builtin_atomic_compare_exchange(), expand_ifn_atomic_compare_exchange(), find_reload_regs(), gimple_build_eh_filter(), gimple_eh_filter_set_failure(), gimplify_expr(), and reload().
|
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().
|
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().
|
static |
Referenced by emit_input_reload_insns(), and emit_reload_insns().
|
static |
Referenced by emit_input_reload_insns(), and emit_reload_insns().
|
static |
These arrays are filled by emit_reload_insns and its subroutines.
Referenced by emit_input_reload_insns(), and emit_reload_insns().
|
static |
List of all insns needing reloads.
Referenced by calculate_needs_all_insns(), finish_spills(), reload(), and select_reload_regs().
|
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().
|
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().
|
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().
|
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().
|
static |
Count the number of registers that we may be able to eliminate.
Referenced by calculate_elim_costs_all_insns(), calculate_needs_all_insns(), finish_spills(), init_elim_table(), mark_not_eliminable(), reload(), reload_as_needed(), update_eliminables(), and verify_initial_elim_offsets().
|
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().
|
static |
Number of labels in the current function.
Referenced by tree_switch_conversion::switch_conversion::exp_index_transform(), init_eliminable_invariants(), tree_switch_conversion::switch_conversion::is_exp_index_transform_viable(), and set_initial_label_offsets().
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().
|
static |
|
static |
|
static |
Referenced by emit_input_reload_insns(), and emit_reload_insns().
|
static |
Referenced by emit_input_reload_insns(), and emit_reload_insns().
|
static |
Referenced by emit_input_reload_insns(), and emit_reload_insns().
|
static |
Referenced by emit_input_reload_insns(), and emit_reload_insns().
|
static |
Referenced by emit_output_reload_insns(), and emit_reload_insns().
|
static |
Referenced by emit_input_reload_insns(), and emit_reload_insns().
|
static |
Referenced by emit_input_reload_insns(), and emit_reload_insns().
|
static |
Referenced by emit_output_reload_insns(), and emit_reload_insns().
|
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().
|
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().
|
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().
|
static |
Referenced by check_eliminable_occurrences(), eliminate_regs(), eliminate_regs_1(), eliminate_regs_in_insn(), elimination_costs_in_insn(), elimination_effects(), elimination_target_reg_p(), init_elim_table(), mark_not_eliminable(), reload(), set_initial_elim_offsets(), set_label_offsets(), set_offsets_for_label(), update_eliminable_offsets(), update_eliminables(), and verify_initial_elim_offsets().
|
static |
Referenced by init_elim_table().
vec<reg_equivs_t, va_gc>* reg_equivs |
Referenced by do_reload(), eliminate_regs_1(), elimination_effects(), emit_move_list(), fix_reg_equiv_init(), free_reg_equiv(), and grow_reg_equivs().
|
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().
|
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().
|
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().
|
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().
|
static |
Vector to remember old contents of reg_renumber before spilling.
Referenced by finish_spills(), and reload().
|
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().
|
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().
|
static |
Referenced by emit_output_reload_insns(), and emit_reload_insns().
|
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().
|
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().
|
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().
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().
|
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().
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().
|
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().
|
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().
class insn_chain* reload_insn_chain |
List of insn_chain instructions, one for every insn that reload needs to examine.
Referenced by build_insn_chain(), calculate_needs_all_insns(), delete_caller_save_insns(), finish_spills(), insert_one_insn(), maybe_fix_stack_asms(), print_insn_chains(), reload_as_needed(), save_call_clobbered_regs(), and setup_save_areas().
|
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().
|
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().
|
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().
|
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().
|
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().
|
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().
|
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().
|
static |
If reg is in use as a reload reg for a RELOAD_OTHER reload.
Referenced by allocate_reload_reg(), choose_reload_regs_init(), clear_reload_reg_in_use(), mark_reload_reg_in_use(), reload_reg_free_p(), and reload_reg_reaches_end_p().
|
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().
|
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().
|
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().
|
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().
|
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().
|
static |
If reg is in use for a RELOAD_FOR_INSN 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().
|
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().
|
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().
|
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().
|
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().
|
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().
|
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().
|
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().
|
static |
Points to the beginning of the reload_obstack. All insn_chain structures are allocated first.
Referenced by init_reload(), and reload().
|
static |
Set during calculate_needs if an insn needs register elimination.
Referenced by calculate_needs_all_insns(), and reload().
|
static |
Set during calculate_needs if an insn needs an operand changed.
Referenced by calculate_needs_all_insns(), and reload().
|
static |
Set by alter_regs if we spilled a register to the stack.
Referenced by alter_reg(), and reload().
|
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().
|
static |
The cost of spilling each hard reg.
Referenced by count_pseudo(), count_spilled_pseudo(), find_reg(), improve_allocation(), ira_caller_save_loop_spill_p(), ira_propagate_hard_reg_costs(), move_spill_restore(), order_regs_for_reload(), and propagate_allocno_info().
|
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().
|
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().
|
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().
|
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().
|
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().
|
static |
Record the stack slot for each spilled hard register.
Referenced by alter_reg(), and reload().
|
static |
Width allocated so far for that stack slot.
Referenced by alter_reg(), and reload().
|
static |
Record which pseudos needed to be spilled.
Referenced by alter_reg(), count_pseudo(), count_spilled_pseudo(), finish_spills(), init_reload(), lra_update_fp2sp_elimination(), reload(), spill_hard_reg(), spill_pseudos(), and spill_pseudos().
Referenced by gen_reload_chain_without_interm_reg_p(), reload(), and substitute().
|
static |
Temporary array of pseudo-register number.
Referenced by finish_spills(), and reload().
|
static |
List of insn chains that are currently unused.
Referenced by calculate_needs_all_insns(), delete_caller_save_insns(), new_insn_chain(), and reload().
|
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().
|
static |
This is used to keep track of the spill regs used in one insn.
Referenced by find_reg(), and find_reload_regs().