GCC Middle and Back End API Reference
resource.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "df.h"
#include "memmodel.h"
#include "tm_p.h"
#include "regs.h"
#include "emit-rtl.h"
#include "resource.h"
#include "insn-attr.h"
#include "function-abi.h"
Include dependency graph for resource.cc:

Data Structures

struct  target_info


#define TARGET_HASH_PRIME   257


static void update_live_status (rtx, const_rtx, void *)
static int find_basic_block (rtx_insn *, int)
static rtx_insnnext_insn_no_annul (rtx_insn *)
static rtx_insnfind_dead_or_set_registers (rtx_insn *, struct resources *, rtx *, int, struct resources, struct resources)
void mark_referenced_resources (rtx x, struct resources *res, bool include_delayed_effects)
void mark_set_resources (rtx x, struct resources *res, int in_dest, enum mark_resource_type mark_type)
static bool return_insn_p (const_rtx insn)
void mark_target_live_regs (rtx_insn *insns, rtx target_maybe_return, struct resources *res)
void init_resource_info (rtx_insn *epilogue_insn)
void free_resource_info (void)
void clear_hashed_info_for_insn (rtx_insn *insn)
void clear_hashed_info_until_next_barrier (rtx_insn *insn)
void incr_ticks_for_insn (rtx_insn *insn)
void mark_end_of_function_resources (rtx trial, bool include_delayed_effects)


static struct resources start_of_epilogue_needs
static struct resources end_of_function_needs
static struct target_info ** target_hash_table = NULL
static int * bb_ticks
static HARD_REG_SET current_live_regs
static HARD_REG_SET pending_dead_regs

Macro Definition Documentation


#define TARGET_HASH_PRIME   257

Function Documentation

◆ clear_hashed_info_for_insn()

void clear_hashed_info_for_insn ( rtx_insn * insn)
Clear any hashed information that we have stored for INSN.   

References ggc_alloc(), INSN_UID(), NULL, TARGET_HASH_PRIME, and target_hash_table.

Referenced by add_to_delay_list(), and clear_hashed_info_until_next_barrier().

◆ clear_hashed_info_until_next_barrier()

void clear_hashed_info_until_next_barrier ( rtx_insn * insn)
Clear any hashed information that we have stored for instructions
between INSN and the next BARRIER that follow a JUMP or a LABEL.   

References BARRIER_P, clear_hashed_info_for_insn(), JUMP_P, LABEL_P, target_info::next, next_active_insn(), and next_nonnote_insn().

Referenced by relax_delay_slots().

◆ find_basic_block()

static int find_basic_block ( rtx_insn * insn,
int search_limit )
Find the number of the basic block with correct live register
information that starts closest to INSN.  Return -1 if we couldn't
find such a basic block or the beginning is more than
SEARCH_LIMIT instructions before INSN.  Use SEARCH_LIMIT = -1 for
an unlimited search.

The delay slot filling code destroys the control-flow graph so,
instead of finding the basic block containing INSN, we search
backwards toward a BARRIER where the live register information is

References BARRIER_P, BLOCK_FOR_INSN(), cfun, ENTRY_BLOCK_PTR_FOR_FN, ggc_alloc(), basic_block_def::index, LABEL_P, next_nonnote_insn(), and prev_nonnote_insn().

Referenced by incr_ticks_for_insn(), and mark_target_live_regs().

◆ find_dead_or_set_registers()

static rtx_insn * find_dead_or_set_registers ( rtx_insn * target,
struct resources * res,
rtx * jump_target,
int jump_count,
struct resources set,
struct resources needed )
A subroutine of mark_target_live_regs.  Search forward from TARGET
looking for registers that are set before they are used.  These are dead.
Stop after passing a few conditional jumps, and/or a small
number of unconditional branches.   

References any_condjump_p(), ANY_RETURN_P, any_uncondjump_p(), can_throw_internal(), CLEAR_HARD_REG_SET, rtx_sequence::element(), find_dead_or_set_registers(), GET_CODE, ggc_alloc(), i, INSN_ANNULLED_BRANCH_P, INSN_FROM_TARGET_P, INSN_P, JUMP_LABEL, JUMP_P, rtx_sequence::len(), mark_referenced_resources(), mark_set_resources(), MARK_SRC_DEST_CALL, NEXT_INSN(), next_insn(), NULL, PATTERN(), pending_dead_regs, resources::regs, scratch, this_insn, and XEXP.

Referenced by find_dead_or_set_registers(), and mark_target_live_regs().

◆ free_resource_info()

void free_resource_info ( void )
Free up the resources allocated to mark_target_live_regs ().  This
should be invoked after the last call to mark_target_live_regs ().   

References BB_HEAD, bb_ticks, BLOCK_FOR_INSN(), cfun, FOR_EACH_BB_FN, free(), i, LABEL_P, target_info::next, NULL, TARGET_HASH_PRIME, and target_hash_table.

Referenced by dbr_schedule().

◆ incr_ticks_for_insn()

void incr_ticks_for_insn ( rtx_insn * insn)
Increment the tick count for the basic block that contains INSN.   

References b, bb_ticks, find_basic_block(), and ggc_alloc().

Referenced by reorg_redirect_jump(), and update_block().

◆ init_resource_info()

◆ mark_end_of_function_resources()

void mark_end_of_function_resources ( rtx trial,
bool include_delayed_effects )
Add TRIAL to the set of resources used at the end of the current

References end_of_function_needs, ggc_alloc(), and mark_referenced_resources().

◆ mark_referenced_resources()

◆ mark_set_resources()

◆ mark_target_live_regs()

void mark_target_live_regs ( rtx_insn * insns,
rtx target_maybe_return,
struct resources * res )
Set the resources that are live at TARGET.

If TARGET is zero, we refer to the end of the current function and can
return our precomputed value.

Otherwise, we try to find out what is live by consulting the basic block
information.  This is tricky, because we must consider the actions of
reload and jump optimization, which occur after the basic block information
has been computed.

Accordingly, we proceed as follows::

We find the previous BARRIER and look at all immediately following labels
(with no intervening active insns) to see if any of them start a basic
block.  If we hit the start of the function first, we use block 0.

Once we have found a basic block and a corresponding first insn, we can
accurately compute the live status (by starting at a label following a
BARRIER, we are immune to actions taken by reload and jump.)  Then we
scan all insns between that point and our target.  For each CLOBBER (or
for call-clobbered regs when we pass a CALL_INSN), mark the appropriate
registers are dead.  For a SET, mark them as live.

We have to be careful when using REG_DEAD notes because they are not
updated by such things as find_equiv_reg.  So keep track of registers
marked as dead that haven't been assigned to, and mark them dead at the
next CODE_LABEL since reload and jump won't propagate values across labels.

If we cannot find the start of a basic block (should be a very rare
case, if it can happen at all), mark everything as potentially live.

Next, scan forward from TARGET looking for things set or clobbered
before they are used.  These are not live.

Because we can be called many times on the same target, save our results
in a hash table indexed by INSN_UID.  This is only done if the function
init_resource_info () was invoked before we are called.   

References add_to_hard_reg_set(), ANY_RETURN_P, b, BASIC_BLOCK_FOR_FN, BB_HEAD, bb_ticks, BLOCK_FOR_INSN(), CALL_P, resources::cc, cfun, CLEAR_HARD_REG_SET, CLEAR_RESOURCE, current_live_regs, DEBUG_INSN_P, DF_LR_IN, DF_REF_AT_TOP, DF_REF_FLAGS, DF_REF_REGNO, end_of_function_needs, ENTRY_BLOCK_PTR_FOR_FN, find_basic_block(), find_dead_or_set_registers(), FOR_EACH_ARTIFICIAL_DEF, function_abi::full_reg_clobbers(), GET_CODE, GET_MODE, ggc_alloc(), global_regs, i, insn_callee_abi(), INSN_FROM_TARGET_P, INSN_P, INSN_UID(), insns, JUMP_P, LABEL_P, mark_referenced_resources(), mark_set_resources(), MARK_SRC_DEST_CALL, mark_target_live_regs(), resources::memory, next_active_insn(), next_insn(), next_insn_no_annul(), NONJUMP_INSN_P, NOTE_KIND, NOTE_P, note_stores(), NULL, PATTERN(), pending_dead_regs, PREV_INSN(), REG_NOTE_KIND, REG_NOTES, REG_P, REG_SET_TO_HARD_REG_SET, REGNO, resources::regs, remove_from_hard_reg_set(), return_insn_p(), scratch, SET_HARD_REG_BIT, SET_HARD_REG_SET, start_of_epilogue_needs, TARGET_HASH_PRIME, target_hash_table, update_live_status(), resources::volatil, and XEXP.

Referenced by fill_slots_from_thread(), and mark_target_live_regs().

◆ next_insn_no_annul()

static rtx_insn * next_insn_no_annul ( rtx_insn * insn)
Similar to next_insn, but ignores insns in the delay slots of
an annulled branch.   


Referenced by mark_target_live_regs().

◆ return_insn_p()

static bool return_insn_p ( const_rtx insn)
Return TRUE if INSN is a return, possibly with a filled delay slot.   

References ANY_RETURN_P, GET_CODE, ggc_alloc(), JUMP_P, NONJUMP_INSN_P, PATTERN(), return_insn_p(), and XVECEXP.

Referenced by init_resource_info(), mark_target_live_regs(), and return_insn_p().

◆ update_live_status()

static void update_live_status ( rtx dest,
const_rtx x,
void * data )
Utility function called from mark_target_live_regs via note_stores.
It deadens any CLOBBERed registers and livens any SET registers.   

References CLEAR_HARD_REG_BIT, current_live_regs, END_REGNO(), GET_CODE, ggc_alloc(), i, pending_dead_regs, REG_P, REGNO, SET_HARD_REG_BIT, subreg_nregs(), SUBREG_REG, and subreg_regno().

Referenced by mark_target_live_regs().

Variable Documentation

◆ bb_ticks

int* bb_ticks
For each basic block, we maintain a generation number of its basic
block info, which is updated each time we move an insn from the
target of a jump.  This is the generation number indexed by block

Referenced by free_resource_info(), incr_ticks_for_insn(), init_resource_info(), and mark_target_live_regs().

◆ current_live_regs

HARD_REG_SET current_live_regs
Marks registers possibly live at the current place being scanned by
mark_target_live_regs.  Also used by update_live_status.   

Referenced by mark_target_live_regs(), and update_live_status().

◆ end_of_function_needs

struct resources end_of_function_needs
Indicates what resources are required at function end.   

Referenced by init_resource_info(), mark_end_of_function_resources(), and mark_target_live_regs().

◆ pending_dead_regs

HARD_REG_SET pending_dead_regs
Marks registers for which we have seen a REG_DEAD note but no assignment.
Also only used by the next two functions.   

Referenced by find_dead_or_set_registers(), mark_target_live_regs(), and update_live_status().

◆ start_of_epilogue_needs

struct resources start_of_epilogue_needs
Indicates what resources are required at the beginning of the epilogue.   

Referenced by init_resource_info(), and mark_target_live_regs().

◆ target_hash_table

struct target_info** target_hash_table = NULL