GCC Middle and Back End API Reference
|
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "rtl.h"
#include "tree.h"
#include "predict.h"
#include "df.h"
#include "memmodel.h"
#include "tm_p.h"
#include "insn-config.h"
#include "regs.h"
#include "emit-rtl.h"
#include "recog.h"
#include "reload.h"
#include "alias.h"
#include "addresses.h"
#include "dumpfile.h"
#include "rtl-iter.h"
#include "target.h"
#include "function-abi.h"
#include "gt-caller-save.h"
Data Structures | |
struct | saved_hard_reg |
Macros | |
#define | MOVE_MAX_WORDS (MOVE_MAX / UNITS_PER_WORD) |
#define | regno_save_mode (this_target_reload->x_regno_save_mode) |
#define | cached_reg_save_code (this_target_reload->x_cached_reg_save_code) |
#define | cached_reg_restore_code (this_target_reload->x_cached_reg_restore_code) |
Typedefs | |
typedef void | refmarker_fn(rtx *loc, machine_mode mode, int hardregno, void *mark_arg) |
Functions | |
static int | reg_save_code (int, machine_mode) |
static int | reg_restore_code (int, machine_mode) |
static void | initiate_saved_hard_regs (void) |
static void | new_saved_hard_reg (int, int) |
static void | finish_saved_hard_regs (void) |
static int | saved_hard_reg_compare_func (const void *, const void *) |
static void | mark_set_regs (rtx, const_rtx, void *) |
static void | mark_referenced_regs (rtx *, refmarker_fn *mark, void *mark_arg) |
static int | insert_save (class insn_chain *, int, HARD_REG_SET *, machine_mode *) |
static int | insert_restore (class insn_chain *, int, int, int, machine_mode *) |
static class insn_chain * | insert_one_insn (class insn_chain *, int, int, rtx) |
static void | add_stored_regs (rtx, const_rtx, void *) |
void | init_caller_save (void) |
void | init_save_areas (void) |
void | setup_save_areas (void) |
void | save_call_clobbered_regs (void) |
static void | mark_reg_as_referenced (rtx *loc, machine_mode mode, int hardregno, void *arg) |
static void | replace_reg_with_saved_mem (rtx *loc, machine_mode mode, int regno, void *arg) |
static void | add_used_regs (rtx *loc, void *data) |
Variables | |
static rtx | regno_save_mem [FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX/MIN_UNITS_PER_WORD+1] |
static int | save_slots_num |
static rtx | save_slots [FIRST_PSEUDO_REGISTER] |
static HARD_REG_SET | hard_regs_saved |
static int | n_regs_saved |
static HARD_REG_SET | referenced_regs |
static refmarker_fn | mark_reg_as_referenced |
static refmarker_fn | replace_reg_with_saved_mem |
static rtx | savepat |
static rtx | restpat |
static rtx | test_reg |
static rtx | test_mem |
static rtx_insn * | saveinsn |
static rtx_insn * | restinsn |
static struct saved_hard_reg * | hard_reg_map [FIRST_PSEUDO_REGISTER] |
static int | saved_regs_num |
static struct saved_hard_reg * | all_saved_regs [FIRST_PSEUDO_REGISTER] |
#define cached_reg_restore_code (this_target_reload->x_cached_reg_restore_code) |
Referenced by reg_restore_code(), and reg_save_code().
#define cached_reg_save_code (this_target_reload->x_cached_reg_save_code) |
Referenced by reg_save_code().
#define MOVE_MAX_WORDS (MOVE_MAX / UNITS_PER_WORD) |
Save and restore call-clobbered registers which are live across a call. Copyright (C) 1989-2025 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/>.
Referenced by init_caller_save(), init_save_areas(), insert_save(), save_call_clobbered_regs(), and setup_save_areas().
#define regno_save_mode (this_target_reload->x_regno_save_mode) |
Referenced by init_caller_save(), save_call_clobbered_regs(), and setup_save_areas().
typedef void refmarker_fn(rtx *loc, machine_mode mode, int hardregno, void *mark_arg) |
Here from note_stores when an insn stores a value in a register. Set the proper bit or bits in the passed regset. All pseudos that have been assigned hard regs have had their register number changed already, so we can ignore pseudos.
References end_hard_regno(), GET_CODE, GET_MODE, i, REG_P, REGNO, SET_REGNO_REG_SET, SUBREG_BYTE, subreg_nregs(), SUBREG_REG, and subreg_regno_offset().
Referenced by insert_one_insn().
|
static |
A note_uses callback used by insert_one_insn. Add the hard-register equivalent of each REG to regset DATA.
References bitmap_set_range(), FOR_EACH_SUBRTX, gcc_checking_assert, HARD_REGISTER_NUM_P, REG_NREGS, REG_P, reg_renumber, and REGNO.
Referenced by insert_one_insn().
|
static |
Free memory allocated for the saved hard registers.
References all_saved_regs, free(), i, and saved_regs_num.
Referenced by setup_save_areas().
void init_caller_save | ( | void | ) |
Initialize for caller-save. Look at all the hard registers that are used by a call and for which reginfo.cc has not already excluded from being used across a call. Ensure that we can find a mode to save the register and that there is a simple insn to save and restore the register. This latter check avoids problems that would occur if we tried to save the MQ register of some machines directly into memory.
References ADDR_SPACE_GENERIC, base_reg_class(), caller_save_initialized_p, CLEAR_HARD_REG_BIT, gcc_assert, gen_int_mode(), gen_rtx_INSN(), gen_rtx_MEM(), gen_rtx_REG(), HARD_REGNO_CALLER_SAVE_MODE, HOST_BITS_PER_INT, i, LAST_VIRTUAL_REGISTER, MOVE_MAX_WORDS, reg_class_contents, reg_save_code(), regno_save_mode, restinsn, restpat, savable_regs, saveinsn, savepat, strict_memory_address_p, TEST_HARD_REG_BIT, test_mem, test_reg, and word_mode.
Referenced by ira().
void init_save_areas | ( | void | ) |
Initialize save areas by showing that we haven't allocated any yet.
References i, MOVE_MAX_WORDS, regno_save_mem, and save_slots_num.
Referenced by reload().
|
static |
First called function for work with saved hard registers.
References hard_reg_map, i, NULL, and saved_regs_num.
Referenced by setup_save_areas().
|
static |
Emit a new caller-save insn and set the code.
References add_stored_regs(), add_used_regs(), BASIC_BLOCK_FOR_FN, BB_END, BB_HEAD, CALL_INSN_FUNCTION_USAGE, CALL_P, cfun, CLEAR_REG_SET, COPY_REG_SET, emit_insn_after(), emit_insn_before(), INSN_CODE, new_insn_chain(), note_stores(), note_uses(), NULL_RTX, PATTERN(), reload_insn_chain, and XEXP.
Referenced by insert_restore(), insert_save(), and save_call_clobbered_regs().
|
static |
Insert a sequence of insns to restore. Place these insns in front of CHAIN if BEFORE_P is nonzero, behind the insn otherwise. MAXRESTORE is the maximum number of registers which should be restored during this call. It should never be less than 1 since we only work with entire registers. Note that we have verified in init_caller_save that we can do this with a simple SET, so use it. Set INSN_CODE to what we save there since the address might not be valid so the insn might not be recognized. These insns will be reloaded and have register elimination done by find_reload, so we need not worry about that here. Return the extra number of registers saved.
References adjust_address_nv, CLEAR_HARD_REG_BIT, copy_rtx(), gcc_assert, gen_rtx_REG(), GET_MODE, GET_MODE_ALIGNMENT, hard_regno_nregs(), hard_regs_saved, i, insert_one_insn(), MAX_SUPPORTED_STACK_ALIGNMENT, MEM_ALIGN, MIN, n_regs_saved, NULL_RTX, reg_restore_code(), reg_save_code(), regno_save_mem, SET_REGNO_REG_SET, and TEST_HARD_REG_BIT.
Referenced by save_call_clobbered_regs().
|
static |
Like insert_restore above, but save registers instead.
References adjust_address_nv, copy_rtx(), gcc_assert, gen_rtx_REG(), GET_MODE, GET_MODE_ALIGNMENT, hard_regno_nregs(), hard_regs_saved, i, insert_one_insn(), MAX_SUPPORTED_STACK_ALIGNMENT, MEM_ALIGN, MIN, MOVE_MAX_WORDS, n_regs_saved, NULL_RTX, reg_save_code(), regno_save_mem, SET_HARD_REG_BIT, SET_REGNO_REG_SET, and TEST_HARD_REG_BIT.
Referenced by save_call_clobbered_regs().
|
static |
Walk X and record all referenced registers in REFERENCED_REGS.
References GET_CODE, GET_MODE, GET_RTX_FORMAT, GET_RTX_LENGTH, i, mark_referenced_regs(), read_modify_subreg_p(), reg_equiv_address, reg_equiv_mem, REG_P, reg_renumber, REGNO, SET, SET_DEST, SET_SRC, SUBREG_REG, XEXP, XVECEXP, and XVECLEN.
Referenced by mark_referenced_regs(), and save_call_clobbered_regs().
|
static |
Parameter function for mark_referenced_regs() that adds registers present in the insn and in equivalent mems and addresses to referenced_regs.
References add_to_hard_reg_set(), and referenced_regs.
Here from note_stores, or directly from save_call_clobbered_regs, when an insn stores a value in a register. Set the proper bit or bits in this_insn_sets. All pseudos that have been assigned hard regs have had their register number changed already, so we can ignore pseudos.
References END_REGNO(), GET_CODE, i, REG_P, REGNO, SET_HARD_REG_BIT, subreg_nregs(), SUBREG_REG, and subreg_regno().
Referenced by save_call_clobbered_regs(), and setup_save_areas().
|
static |
Allocate and return new saved hard register with given REGNO and CALL_FREQ.
References all_saved_regs, saved_hard_reg::call_freq, saved_hard_reg::first_p, hard_reg_map, saved_hard_reg::hard_regno, saved_hard_reg::next, saved_hard_reg::num, and saved_regs_num.
Referenced by setup_save_areas().
|
static |
Return the INSN_CODE used to restore register REG in mode MODE.
References cached_reg_restore_code, and reg_save_code().
Referenced by insert_restore().
|
static |
Return the INSN_CODE used to save register REG in mode MODE.
References cached_reg_restore_code, cached_reg_save_code, constrain_operands(), extract_insn(), gcc_assert, get_enabled_alternatives(), INSN_CODE, PUT_MODE(), recog_memoized(), reg_save_code(), restinsn, saveinsn, set_mode_and_regno(), targetm, test_mem, and test_reg.
Referenced by init_caller_save(), insert_restore(), insert_save(), reg_restore_code(), and reg_save_code().
|
static |
Parameter function for mark_referenced_regs() that replaces registers referenced in a debug_insn that would have been restored, should it be a non-debug_insn, with their save locations.
References adjust_address_nv, byte_lowpart_offset(), copy_rtx(), gcc_assert, gen_rtx_REG(), GET_MODE, GET_MODE_BITSIZE(), GET_MODE_CLASS, hard_regno_nregs(), hard_regs_saved, i, mode_for_size(), regno_save_mem, opt_mode< T >::require(), rtvec_alloc(), TEST_HARD_REG_BIT, and XVECEXP.
void save_call_clobbered_regs | ( | void | ) |
Find the places where hard regs are live across calls and save them.
References BB_END, BLOCK_FOR_INSN(), CLEAR_HARD_REG_SET, function_abi::clobbers_reg_p(), copy_rtx(), DEBUG_INSN_P, EXECUTE_IF_SET_IN_REG_SET, find_reg_note(), fixed_reg_set, function_abi::full_reg_clobbers(), gcc_assert, GET_CODE, GET_MODE, HARD_REGISTER_P, HARD_REGNO_CALLER_SAVE_MODE, hard_regno_nregs(), hard_regs_saved, insert_one_insn(), insert_restore(), insert_save(), insn_callee_abi(), JUMP_P, last, mark_referenced_regs(), mark_reg_as_referenced, mark_set_regs(), MOVE_MAX_WORDS, n_regs_saved, NEXT_INSN(), NONDEBUG_INSN_P, NOTE_P, note_stores(), NULL, partial_subreg_p(), PATTERN(), PREV_INSN(), PSEUDO_REGNO_MODE, r, referenced_regs, REG_P, reg_renumber, REG_SET_TO_HARD_REG_SET, REGNO, regno_reg_rtx, regno_save_mode, reload_insn_chain, replace_reg_with_saved_mem, savable_regs, SET_DEST, SET_HARD_REG_BIT, SET_NEXT_INSN(), SET_PREV_INSN(), SIBLING_CALL_P, TEST_HARD_REG_BIT, XEXP, and XVECEXP.
Referenced by reload().
|
static |
The function is used to sort the saved hard register structures according their frequency.
References saved_hard_reg::call_freq, and saved_hard_reg::num.
Referenced by setup_save_areas().
void setup_save_areas | ( | void | ) |
Allocate save areas for any hard registers that might need saving. We take a conservative approach here and look for call-clobbered hard registers that are assigned to pseudos that cross calls. This may overestimate slightly (especially if some of these registers are later used as spill registers), but it should not be significant. For IRA we use priority coloring to decrease stack slots needed for saving hard registers through calls. We build conflicts for them to do coloring. Future work: In the fallback case we should iterate backwards across all possible modes for the save, choosing the largest available one instead of falling back to the smallest mode immediately. (eg TF -> DF -> SF). We do not try to use "move multiple" instructions that exist on some machines (such as the 68k moveml). It could be a win to try and use them when possible. The hard part is doing it in a way that is machine independent since they might be saving non-consecutive registers. (imagine caller-saving d0,d1,a0,a1 on the 68k)
References adjust_address_nv, all_saved_regs, ASLK_REDUCE_ALIGN, assign_stack_local_1(), BLOCK_FOR_INSN(), CALL_P, CLEAR_HARD_REG_SET, crtl, dump_file, EXECUTE_IF_SET_IN_REG_SET, find_reg_note(), finish_saved_hard_regs(), saved_hard_reg::first_p, fixed_reg_set, free(), function_abi::full_reg_clobbers(), gcc_assert, get_frame_alias_set(), GET_MODE, GET_MODE_SIZE(), hard_reg_map, saved_hard_reg::hard_regno, hard_regno_nregs(), i, initiate_saved_hard_regs(), insn_callee_abi(), known_le, mark_set_regs(), MOVE_MAX_WORDS, new_saved_hard_reg(), saved_hard_reg::next, note_stores(), NULL, NULL_RTX, saved_hard_reg::num, PSEUDO_REGNO_MODE, qsort, r, REG_FREQ_FROM_BB, reg_renumber, REG_SET_TO_HARD_REG_SET, regno_reg_rtx, regno_save_mem, regno_save_mode, reload_insn_chain, savable_regs, save_slots, save_slots_num, saved_hard_reg_compare_func(), saved_regs_num, SET_HARD_REG_BIT, set_mem_alias_set(), SIBLING_CALL_P, saved_hard_reg::slot, TEST_HARD_REG_BIT, used_regs, and XEXP.
Referenced by reload().
|
static |
Pointers to all the structures. Index is the order number of the corresponding structure.
Referenced by finish_saved_hard_regs(), new_saved_hard_reg(), and setup_save_areas().
|
static |
Map: hard register number to the corresponding structure.
Referenced by initiate_saved_hard_regs(), new_saved_hard_reg(), and setup_save_areas().
|
static |
Set of hard regs currently residing in save area (during insn scan).
Referenced by insert_restore(), insert_save(), replace_reg_with_saved_mem(), and save_call_clobbered_regs().
|
static |
Referenced by save_call_clobbered_regs().
|
static |
Number of registers currently in hard_regs_saved.
Referenced by insert_restore(), insert_save(), and save_call_clobbered_regs().
|
static |
Computed by mark_referenced_regs, all regs referenced in a given insn.
Referenced by mark_reg_as_referenced(), and save_call_clobbered_regs().
|
static |
For each hard register, a place on the stack where it can be saved, if needed.
Referenced by init_save_areas(), insert_restore(), insert_save(), replace_reg_with_saved_mem(), and setup_save_areas().
|
static |
Referenced by save_call_clobbered_regs().
|
static |
Referenced by init_caller_save(), and reg_save_code().
|
static |
Referenced by init_caller_save().
|
static |
Allocated slots so far.
Referenced by setup_save_areas().
|
static |
The number of elements in the subsequent array.
Referenced by init_save_areas(), and setup_save_areas().
|
static |
The number of all structures representing hard registers should be saved, in order words, the number of used elements in the following array.
Referenced by finish_saved_hard_regs(), initiate_saved_hard_regs(), new_saved_hard_reg(), and setup_save_areas().
|
static |
Referenced by init_caller_save(), and reg_save_code().
|
static |
Referenced by init_caller_save().
|
static |
Referenced by init_caller_save(), and reg_save_code().
|
static |
Referenced by init_caller_save(), and reg_save_code().