GCC Middle and Back End API Reference
lra-eliminations.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "tree.h"
#include "df.h"
#include "memmodel.h"
#include "tm_p.h"
#include "optabs.h"
#include "regs.h"
#include "ira.h"
#include "recog.h"
#include "output.h"
#include "rtl-error.h"
#include "lra-int.h"
Include dependency graph for lra-eliminations.cc:

Data Structures

class  lra_elim_table
struct  elim_table_1


#define NUM_ELIMINABLE_REGS   ARRAY_SIZE (reg_eliminate_1)


static void print_elim_table (FILE *f)
void lra_debug_elim_table (void)
static void setup_can_eliminate (class lra_elim_table *ep, bool value)
static void setup_elimination_map (void)
static rtx form_sum (rtx x, rtx y)
int lra_get_elimination_hard_regno (int hard_regno)
static class lra_elim_tableget_elimination (rtx reg)
static rtx move_plus_up (rtx x)
rtx lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode, bool subst_p, bool update_p, poly_int64 update_sp_offset, bool full_p)
rtx lra_eliminate_regs (rtx x, machine_mode mem_mode, rtx insn)
static void mark_not_eliminable (rtx x, machine_mode mem_mode)
void eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p, poly_int64 update_sp_offset)
static int spill_pseudos (HARD_REG_SET set, int *spilled_pseudos)
static bool update_reg_eliminate (bitmap insns_with_changed_offsets)
static void init_elim_table (void)
static void init_elimination (void)
poly_int64 lra_update_sp_offset (rtx x, poly_int64 offset)
void lra_eliminate_reg_if_possible (rtx *loc)
static void process_insn_for_elimination (rtx_insn *insn, bool final_p, bool first_p)
int lra_update_fp2sp_elimination (int *spilled_pseudos)
void lra_eliminate (bool final_p, bool first_p)


static class lra_elim_tablereg_eliminate = 0
static const struct elim_table_1 reg_eliminate_1 []
static class lra_elim_tableelimination_map [FIRST_PSEUDO_REGISTER]
static class lra_elim_table self_elim_table
static poly_int64 self_elim_offsets [FIRST_PSEUDO_REGISTER]
static rtx eliminable_reg_rtx [FIRST_PSEUDO_REGISTER]
static bool elimination_fp2sp_occured_p = false
static poly_int64 curr_sp_change

Macro Definition Documentation


Function Documentation

◆ eliminate_regs_in_insn()

void eliminate_regs_in_insn ( rtx_insn * insn,
bool replace_p,
bool first_p,
poly_int64 update_sp_offset )
Scan INSN and eliminate all eliminable hard registers in it.

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

If REPLACE_P is false, just update the offsets while keeping the
base register the same.  If FIRST_P, use the sp offset for
elimination to sp.  Otherwise, use UPDATE_SP_OFFSET for this.  If
UPDATE_SP_OFFSET is non-zero, don't use difference of the offset
and the previous offset.  Attach the note about used elimination
for insns setting frame pointer to update elimination easy (without
parsing already generated elimination insns to find offset
previously used) in future.   

References asm_noperands(), lra_elim_table::can_eliminate, DEBUG_INSN_P, lra_static_insn_data::dup_num, lra_elim_table::from_rtx, gen_lowpart, GET_CODE, get_elimination(), GET_MODE, have_addptr3_insn(), i, insn_data, ira_reg_equiv, ira_reg_equiv_len, known_eq, lra_assert, lra_eliminate_regs_1(), lra_get_insn_recog_data(), lra_pmode_pseudo, lra_update_insn_recog_data(), lra_static_insn_data::n_dups, lra_static_insn_data::n_operands, NULL, NULL_RTX, NUM_ELIMINABLE_REGS, lra_elim_table::offset, offset, OP_IN, lra_static_insn_data::operand, PATTERN(), plus_constant(), poly_int_rtx_p(), lra_elim_table::previous_offset, recog_memoized(), reg_eliminate, REG_P, REGNO, SET_DEST, SET_SRC, single_set(), stack_pointer_rtx, subreg_lowpart_p(), SUBREG_REG, lra_elim_table::to_rtx, trunc_int_for_mode(), lra_operand_data::type, validate_change(), and XEXP.

Referenced by change_sp_offset(), lra_process_new_insns(), and process_insn_for_elimination().

◆ form_sum()

static rtx form_sum ( rtx x,
rtx y )
Compute the sum of X and Y, making canonicalizations assumed in an
address, namely: sum constant integers, surround the sum of two
constants with a CONST, put the constant as the second operand, and
group the constant on the outermost sum.

This routine assumes both inputs are already in canonical form.   

References CONSTANT_P, form_sum(), GET_CODE, GET_MODE, offset, plus_constant(), poly_int_rtx_p(), XEXP, and y.

Referenced by eliminate_regs_1(), form_sum(), and lra_eliminate_regs_1().

◆ get_elimination()

◆ init_elim_table()

◆ init_elimination()

static void init_elimination ( void )

◆ lra_debug_elim_table()

void lra_debug_elim_table ( void )
Print info about elimination table to stderr.   

References print_elim_table().

◆ lra_eliminate()

◆ lra_eliminate_reg_if_possible()

void lra_eliminate_reg_if_possible ( rtx * loc)
Eliminate hard reg given by its location LOC.   

References get_elimination(), lra_assert, lra_no_alloc_regs, NULL, REG_P, REGNO, TEST_HARD_REG_BIT, and lra_elim_table::to_rtx.

Referenced by in_class_p().

◆ lra_eliminate_regs()

rtx lra_eliminate_regs ( rtx x,
machine_mode mem_mode,
rtx insn )
This function is used externally in subsequent passes of GCC.  It
always does a full elimination of X.      

References lra_eliminate_regs_1(), and NULL.

Referenced by based_loc_descr(), compute_frame_pointer_to_fb_displacement(), reg_loc_descriptor(), and vt_initialize().

◆ lra_eliminate_regs_1()

rtx lra_eliminate_regs_1 ( rtx_insn * insn,
rtx x,
machine_mode mem_mode,
bool subst_p,
bool update_p,
poly_int64 update_sp_offset,
bool full_p )
Scan X and replace any eliminable registers (such as fp) with a
replacement (such as sp) if SUBST_P, plus an offset.  The offset is
a change in the offset between the eliminable register and its
substitution if UPDATE_P, or the full offset if FULL_P, or
otherwise zero.  If FULL_P, we also use the SP offsets for
elimination to SP.  If UPDATE_P, use UPDATE_SP_OFFSET for updating
offsets of register elimnable to SP.  If UPDATE_SP_OFFSET is
non-zero, don't use difference of the offset and the previous

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 hard register
and the constant zero with the hard register, which we cannot do
outside a MEM.  In addition, we need to record the fact that a
hard register is referenced outside a MEM.

If we make full substitution to SP for non-null INSN, add the insn
sp offset.   

References alloc_reg_note(), alter_subreg(), CASE_CONST_ANY, CONST_INT_P, CONSTANT_P, current_function_decl, DEBUG_INSN_P, elimination_fp2sp_occured_p, form_sum(), lra_elim_table::from, lra_elim_table::from_rtx, gcc_assert, gcc_unreachable, gen_rtvec_v(), GET_CODE, get_elimination(), GET_MODE, GET_RTX_FORMAT, GET_RTX_LENGTH, i, INTVAL, known_eq, lra_assert, lra_eliminate_regs_1(), lra_get_insn_recog_data(), MEM_P, move_plus_up(), NULL, NULL_RTX, lra_elim_table::offset, offset, paradoxical_subreg_p(), plus_constant(), poly_int_rtx_p(), lra_elim_table::previous_offset, REG_NOTE_KIND, REG_P, replace_equiv_address_nv(), SET, shallow_copy_rtx(), simplify_gen_binary(), simplify_gen_subreg(), stack_pointer_rtx, SUBREG_BYTE, SUBREG_REG, lra_elim_table::to, lra_elim_table::to_rtx, XEXP, XVEC, XVECEXP, and XVECLEN.

Referenced by eliminate_regs_in_insn(), get_equiv_with_elimination(), lra_eliminate_regs(), lra_eliminate_regs_1(), and remove_pseudos().

◆ lra_get_elimination_hard_regno()

int lra_get_elimination_hard_regno ( int hard_regno)
Return the current substitution hard register of the elimination of
HARD_REGNO.     If HARD_REGNO is not eliminable, return itself.   

References elimination_map, NULL, and lra_elim_table::to.

Referenced by get_hard_regno(), get_reg_class(), and process_alt_operands().

◆ lra_update_fp2sp_elimination()

int lra_update_fp2sp_elimination ( int * spilled_pseudos)
Update frame pointer to stack pointer elimination if we started with
permitted frame pointer elimination and now target reports that we can not
do this elimination anymore.  Record spilled pseudos in SPILLED_PSEUDOS
unless it is null, and return the recorded pseudos number.   

References add_to_hard_reg_set(), CLEAR_HARD_REG_SET, elimination_fp2sp_occured_p, frame_pointer_needed, lra_elim_table::from, gcc_assert, HARD_FRAME_POINTER_REGNUM, lra_dump_file, NULL, NUM_ELIMINABLE_REGS, reg_eliminate, setup_can_eliminate(), spill_pseudos(), spilled_pseudos, targetm, and lra_elim_table::to.

Referenced by lra_spill().

◆ lra_update_sp_offset()

poly_int64 lra_update_sp_offset ( rtx x,
poly_int64 offset )
Update and return stack pointer OFFSET after processing X.   

References curr_sp_change, mark_not_eliminable(), and offset.

Referenced by setup_sp_offset().

◆ mark_not_eliminable()

static void mark_not_eliminable ( rtx x,
machine_mode mem_mode )
Scan rtx X for references to elimination source or target registers
in contexts that would prevent the elimination from happening.
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 curr_sp_change, lra_elim_table::from_rtx, GET_CODE, GET_MODE, GET_MODE_SIZE(), GET_RTX_FORMAT, GET_RTX_LENGTH, hard_frame_pointer_rtx, i, mark_not_eliminable(), NUM_ELIMINABLE_REGS, offset, poly_int_rtx_p(), reg_eliminate, REG_P, REGNO, SET, SET_DEST, SET_SRC, setup_can_eliminate(), stack_pointer_rtx, lra_elim_table::to_rtx, XEXP, XVECEXP, and XVECLEN.

Referenced by init_elimination(), lra_update_sp_offset(), and mark_not_eliminable().

◆ move_plus_up()

static rtx move_plus_up ( rtx x)
Transform (subreg (plus reg const)) to (plus (subreg reg) const)
when it is possible.  Return X or the transformation result if the
transformation is done.   

References CONSTANT_P, GET_CODE, GET_MODE, GET_MODE_CLASS, lowpart_subreg(), paradoxical_subreg_p(), simplify_subreg(), subreg_lowpart_offset(), subreg_lowpart_p(), SUBREG_REG, and XEXP.

Referenced by lra_eliminate_regs_1().

◆ print_elim_table()

static void print_elim_table ( FILE * f)

◆ process_insn_for_elimination()

static void process_insn_for_elimination ( rtx_insn * insn,
bool final_p,
bool first_p )
Do (final if FINAL_P or first if FIRST_P) elimination in INSN.  Add
the insn for subsequent processing in the constraint pass, update
the insn info.   

References check_and_force_assignment_correctness_p, eliminate_regs_in_insn(), INSN_CODE, lra_push_insn(), lra_set_used_insn_alternative(), LRA_UNKNOWN_ALT, lra_update_insn_recog_data(), lra_update_insn_regno_info(), PATTERN(), and recog().

Referenced by lra_eliminate().

◆ setup_can_eliminate()

static void setup_can_eliminate ( class lra_elim_table * ep,
bool value )
Setup possibility of elimination in elimination table element EP to
VALUE.  Setup FRAME_POINTER_NEEDED if elimination from frame
pointer to stack pointer is not possible anymore.   

References lra_elim_table::can_eliminate, frame_pointer_needed, lra_elim_table::from, HARD_FRAME_POINTER_REGNUM, lra_elim_table::prev_can_eliminate, REGNO_POINTER_ALIGN, and lra_elim_table::to.

Referenced by init_elim_table(), init_elimination(), lra_update_fp2sp_elimination(), mark_not_eliminable(), and update_reg_eliminate().

◆ setup_elimination_map()

static void setup_elimination_map ( void )
Set up ELIMINATION_MAP of the currently used eliminations.   

References lra_elim_table::can_eliminate, elimination_map, lra_elim_table::from, i, NULL, NUM_ELIMINABLE_REGS, and reg_eliminate.

Referenced by init_elimination(), and update_reg_eliminate().

◆ spill_pseudos()

static int spill_pseudos ( HARD_REG_SET set,
int * spilled_pseudos )
Spill pseudos which are assigned to hard registers in SET, record them in
SPILLED_PSEUDOS unless it is null, and return the recorded pseudos number.
Add affected insns for processing in the subsequent constraint pass.   

References bitmap_bit_p, bitmap_clear(), bitmap_initialize(), bitmap_ior_into(), get_insns(), hard_reg_set_empty_p(), i, INSN_UID(), lra_dump_file, lra_no_alloc_regs, lra_push_insn(), lra_reg_info, lra_set_used_insn_alternative(), LRA_UNKNOWN_ALT, max_reg_num(), NEXT_INSN(), NULL, NULL_RTX, overlaps_hard_reg_set_p(), PSEUDO_REGNO_MODE, reg_obstack, reg_renumber, spilled_pseudos, and TEST_HARD_REG_BIT.

◆ update_reg_eliminate()

static bool update_reg_eliminate ( bitmap insns_with_changed_offsets)
Update all offsets and possibility for elimination on eliminable
registers.  Spill pseudos assigned to registers which are
uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET.  Add
insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard
registers whose offsets should be changed.  Return true if any
elimination offset changed.   

References add_to_hard_reg_set(), bitmap_ior_into(), lra_elim_table::can_eliminate, CLEAR_HARD_REG_SET, eliminable_regset, elimination_fp2sp_occured_p, elimination_map, fixed_regs, lra_elim_table::from, gcc_assert, lra_reg::insn_bitmap, known_eq, lra_assert, lra_dump_file, lra_no_alloc_regs, lra_reg_info, lra_update_reg_val_offset(), NULL, NUM_ELIMINABLE_REGS, lra_elim_table::offset, lra_elim_table::prev_can_eliminate, lra_elim_table::previous_offset, reg_eliminate, self_elim_offsets, setup_can_eliminate(), setup_elimination_map(), spill_pseudos(), stack_pointer_rtx, targetm, lra_elim_table::to, lra_elim_table::to_rtx, and lra_reg::val.

Referenced by lra_eliminate().

Variable Documentation

◆ curr_sp_change

poly_int64 curr_sp_change
Stack pointer offset before the current insn relative to one at the
func start.  RTL insns can change SP explicitly.  We keep the
changes from one insn to another through this variable.   

Referenced by init_elimination(), lra_update_sp_offset(), and mark_not_eliminable().

◆ eliminable_reg_rtx

rtx eliminable_reg_rtx[FIRST_PSEUDO_REGISTER]
Map: hard regno -> RTL presentation.  RTL presentations of all
potentially eliminable hard registers are stored in the map.      

Referenced by get_elimination(), and init_elim_table().

◆ elimination_fp2sp_occured_p

bool elimination_fp2sp_occured_p = false
Flag that we already did frame pointer to stack pointer elimination.   

Referenced by lra_eliminate(), lra_eliminate_regs_1(), lra_update_fp2sp_elimination(), and update_reg_eliminate().

◆ elimination_map

class lra_elim_table* elimination_map[FIRST_PSEUDO_REGISTER]
Map: eliminable "from" register -> its current elimination,
or NULL if none.  The elimination table may contain more than
one elimination for the same hard register, but this map specifies
the one that we are currently using.   

Referenced by get_elimination(), lra_eliminate(), lra_get_elimination_hard_regno(), setup_elimination_map(), and update_reg_eliminate().

◆ reg_eliminate

class lra_elim_table* reg_eliminate = 0
The elimination table.  Each array entry describes one possible way
of eliminating a register in favor of another.  If there is more
than one way of eliminating a particular register, the most
preferred should be specified first.      

Referenced by eliminate_regs_in_insn(), init_elim_table(), init_elimination(), lra_eliminate(), lra_update_fp2sp_elimination(), mark_not_eliminable(), print_elim_table(), setup_elimination_map(), and update_reg_eliminate().

◆ reg_eliminate_1

const struct elim_table_1 reg_eliminate_1[]
Initial value:

Referenced by init_elim_table().

◆ self_elim_offsets

poly_int64 self_elim_offsets[FIRST_PSEUDO_REGISTER]
Offsets should be used to restore original offsets for eliminable
hard register which just became not eliminable.  Zero,

Referenced by get_elimination(), init_elim_table(), and update_reg_eliminate().

◆ self_elim_table

class lra_elim_table self_elim_table
When an eliminable hard register becomes not eliminable, we use the
following special structure to restore original offsets for the

Referenced by get_elimination(), and init_elim_table().