GCC Middle and Back End API Reference
cse.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 "cfghooks.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 "cfgrtl.h"
#include "cfganal.h"
#include "cfgcleanup.h"
#include "alias.h"
#include "toplev.h"
#include "rtlhooks-def.h"
#include "tree-pass.h"
#include "dbgcnt.h"
#include "rtl-iter.h"
#include "function-abi.h"
#include "rtlanal.h"
#include "expr.h"
Include dependency graph for cse.cc:

Data Structures

struct  qty_table_elem
 
struct  reg_eqv_elem
 
struct  cse_reg_info
 
struct  table_elt
 
struct  branch_path
 
struct  cse_basic_block_data
 
struct  set
 

Macros

#define HASH_SHIFT   5
 
#define HASH_SIZE   (1 << HASH_SHIFT)
 
#define HASH_MASK   (HASH_SIZE - 1)
 
#define FIXED_REGNO_P(N)
 
#define CHEAP_REGNO(N)
 
#define COST(X, MODE)
 
#define COST_IN(X, MODE, OUTER, OPNO)
 
#define REG_TICK(N)
 
#define REG_IN_TABLE(N)
 
#define SUBREG_TICKED(N)
 
#define REG_QTY(N)
 
#define REGNO_QTY_VALID_P(N)
 
#define CHEAPER(X, Y)
 
#define RTL_HOOKS_GEN_LOWPART   gen_lowpart_if_possible
 

Functions

static bool fixed_base_plus_p (rtx x)
 
static int notreg_cost (rtx, machine_mode, enum rtx_code, int)
 
static int preferable (int, int, int, int)
 
static void new_basic_block (void)
 
static void make_new_qty (unsigned int, machine_mode)
 
static void make_regs_eqv (unsigned int, unsigned int)
 
static void delete_reg_equiv (unsigned int)
 
static bool mention_regs (rtx)
 
static bool insert_regs (rtx, struct table_elt *, bool)
 
static void remove_from_table (struct table_elt *, unsigned)
 
static void remove_pseudo_from_table (rtx, unsigned)
 
static struct table_eltlookup (rtx, unsigned, machine_mode)
 
static struct table_eltlookup_for_remove (rtx, unsigned, machine_mode)
 
static rtx lookup_as_function (rtx, enum rtx_code)
 
static struct table_eltinsert_with_costs (rtx, struct table_elt *, unsigned, machine_mode, int, int)
 
static struct table_eltinsert (rtx, struct table_elt *, unsigned, machine_mode)
 
static void merge_equiv_classes (struct table_elt *, struct table_elt *)
 
static void invalidate (rtx, machine_mode)
 
static void remove_invalid_refs (unsigned int)
 
static void remove_invalid_subreg_refs (unsigned int, poly_uint64, machine_mode)
 
static void rehash_using_reg (rtx)
 
static void invalidate_memory (void)
 
static rtx use_related_value (rtx, struct table_elt *)
 
static unsigned canon_hash (rtx, machine_mode)
 
static unsigned safe_hash (rtx, machine_mode)
 
static unsigned hash_rtx_string (const char *)
 
static rtx canon_reg (rtx, rtx_insn *)
 
static enum rtx_code find_comparison_args (enum rtx_code, rtx *, rtx *, machine_mode *, machine_mode *)
 
static rtx fold_rtx (rtx, rtx_insn *)
 
static rtx equiv_constant (rtx)
 
static void record_jump_equiv (rtx_insn *, bool)
 
static void record_jump_cond (enum rtx_code, machine_mode, rtx, rtx)
 
static void cse_insn (rtx_insn *)
 
static void cse_prescan_path (struct cse_basic_block_data *)
 
static void invalidate_from_clobbers (rtx_insn *)
 
static void invalidate_from_sets_and_clobbers (rtx_insn *)
 
static void cse_extended_basic_block (struct cse_basic_block_data *)
 
void dump_class (struct table_elt *)
 
static void get_cse_reg_info_1 (unsigned int regno)
 
static struct cse_reg_infoget_cse_reg_info (unsigned int regno)
 
static void flush_hash_table (void)
 
static bool insn_live_p (rtx_insn *, int *)
 
static bool set_live_p (rtx, int *)
 
static void cse_change_cc_mode_insn (rtx_insn *, rtx)
 
static void cse_change_cc_mode_insns (rtx_insn *, rtx_insn *, rtx)
 
static machine_mode cse_cc_succs (basic_block, basic_block, rtx, rtx, bool)
 
static unsigned HASH (rtx x, machine_mode mode)
 
static unsigned SAFE_HASH (rtx x, machine_mode mode)
 
static int approx_reg_cost (const_rtx x)
 
static void init_cse_reg_info (unsigned int nregs)
 
static bool compute_const_anchors (rtx cst, HOST_WIDE_INT *lower_base, HOST_WIDE_INT *lower_offs, HOST_WIDE_INT *upper_base, HOST_WIDE_INT *upper_offs)
 
static void insert_const_anchor (HOST_WIDE_INT anchor, rtx reg, HOST_WIDE_INT offs, machine_mode mode)
 
static void insert_const_anchors (rtx reg, rtx cst, machine_mode mode)
 
static rtx find_reg_offset_for_const (struct table_elt *anchor_elt, HOST_WIDE_INT offs, unsigned *old)
 
static rtx try_const_anchors (rtx src_const, machine_mode mode)
 
static void remove_from_table (struct table_elt *elt, unsigned int hash)
 
static void remove_pseudo_from_table (rtx x, unsigned int hash)
 
static struct table_eltlookup (rtx x, unsigned int hash, machine_mode mode)
 
static struct table_eltlookup_for_remove (rtx x, unsigned int hash, machine_mode mode)
 
static struct table_eltinsert_with_costs (rtx x, struct table_elt *classp, unsigned int hash, machine_mode mode, int cost, int reg_cost)
 
static struct table_eltinsert (rtx x, struct table_elt *classp, unsigned int hash, machine_mode mode)
 
static bool check_dependence (const_rtx x, rtx exp, machine_mode mode, rtx addr)
 
static void invalidate_reg (rtx x)
 
static void invalidate_dest (rtx dest)
 
static void invalidate_for_call (rtx_insn *insn)
 
unsigned hash_rtx (const_rtx x, machine_mode mode, int *do_not_record_p, int *hash_arg_in_memory_p, bool have_reg_qty, hash_rtx_callback_function cb)
 
bool exp_equiv_p (const_rtx x, const_rtx y, int validate, bool for_gcse)
 
static void validate_canon_reg (rtx *xloc, rtx_insn *insn)
 
static rtx record_jump_cond_subreg (machine_mode mode, rtx op)
 
static void try_back_substitute_reg (rtx set, rtx_insn *insn)
 
static void add_to_set (vec< struct set > *sets, rtx x, bool is_fake_set)
 
static int find_sets_in_insn (rtx_insn *insn, vec< struct set > *psets)
 
static void canon_asm_operands (rtx x, rtx_insn *insn)
 
static void canonicalize_insn (rtx_insn *insn, vec< struct set > *psets)
 
static rtx cse_process_note (rtx)
 
static rtx cse_process_note_1 (rtx x, const_rtx, void *)
 
static bool cse_find_path (basic_block first_bb, struct cse_basic_block_data *data, int follow_jumps)
 
static void cse_dump_path (struct cse_basic_block_data *data, int nsets, FILE *f)
 
static bool have_eh_succ_edges (basic_block bb)
 
static bool check_for_label_ref (rtx_insn *insn)
 
static int cse_main (rtx_insn *f, int nregs)
 
static void count_reg_usage (rtx x, int *counts, rtx dest, int incr)
 
static bool is_dead_reg (const_rtx x, int *counts)
 
static void count_stores (rtx x, const_rtx set, void *data)
 
static bool is_dead_debug_insn (const_rtx pat, int *counts, rtx *replacements, bool *seen_repl)
 
static rtx replace_dead_reg (rtx x, const_rtx old_rtx, void *data)
 
int delete_trivially_dead_insns (rtx_insn *insns, int nreg)
 
static void cse_change_cc_mode (subrtx_ptr_iterator::array_type &array, rtx *loc, rtx_insn *insn, rtx newreg)
 
static void cse_condition_code_reg (void)
 
static unsigned int rest_of_handle_cse (void)
 
rtl_opt_passmake_pass_cse (gcc::context *ctxt)
 
static unsigned int rest_of_handle_cse2 (void)
 
rtl_opt_passmake_pass_cse2 (gcc::context *ctxt)
 
static unsigned int rest_of_handle_cse_after_global_opts (void)
 
rtl_opt_passmake_pass_cse_after_global_opts (gcc::context *ctxt)
 

Variables

static int max_qty
 
static int next_qty
 
static struct qty_table_elemqty_table
 
static rtx_insnthis_insn
 
static bool optimize_this_for_speed_p
 
static struct reg_eqv_elemreg_eqv_table
 
static struct cse_reg_infocse_reg_info_table
 
static unsigned int cse_reg_info_table_size
 
static unsigned int cse_reg_info_table_first_uninitialized
 
static unsigned int cse_reg_info_timestamp
 
static HARD_REG_SET hard_regs_in_table
 
static bool cse_cfg_altered
 
static bool cse_jumps_altered
 
static bool recorded_label_ref
 
static int do_not_record
 
static int hash_arg_in_memory
 
static struct table_elttable [HASH_SIZE]
 
static struct table_eltfree_element_chain
 
static bitmap cse_ebb_live_in
 
static bitmap cse_ebb_live_out
 
static sbitmap cse_visited_basic_blocks
 
static const struct rtl_hooks cse_rtl_hooks = RTL_HOOKS_INITIALIZER
 

Macro Definition Documentation

◆ CHEAP_REGNO

#define CHEAP_REGNO ( N)
Value:
&& FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
#define FIXED_REGNO_P(N)
Definition cse.cc:423
#define N
Definition gensupport.cc:202
#define REGNO_PTR_FRAME_P(REGNUM)
Definition rtl.h:4098
#define HARD_REGISTER_NUM_P(REG_NO)
Definition rtl.h:1977
Compute cost of X, as stored in the `cost' field of a table_elt. Fixed hard registers and pointers into the frame are the cheapest with a cost of 0. Next come pseudos with a cost of one and other hard registers with a cost of 2. Aside from these special cases, call `rtx_cost'.

Referenced by approx_reg_cost().

◆ CHEAPER

#define CHEAPER ( X,
Y )
Value:
(preferable ((X)->cost, (X)->regcost, (Y)->cost, (Y)->regcost) < 0)
static int preferable(int, int, int, int)
Definition cse.cc:671
#define Y
Definition gensupport.cc:203
Compare table_elt X and Y and return true iff X is cheaper than Y.

Referenced by find_reg_offset_for_const(), and insert_with_costs().

◆ COST

#define COST ( X,
MODE )
Value:
(REG_P (X) ? 0 : notreg_cost (X, MODE, SET, 1))
static int notreg_cost(rtx, machine_mode, enum rtx_code, int)
Definition cse.cc:705
@ SET
Definition genmodes.cc:264
#define REG_P(X)
Definition rtl.h:747

Referenced by create_fixup_graph(), cse_insn(), fold_rtx(), insert(), and insert_const_anchor().

◆ COST_IN

#define COST_IN ( X,
MODE,
OUTER,
OPNO )
Value:
(REG_P (X) ? 0 : notreg_cost (X, MODE, OUTER, OPNO))

Referenced by fold_rtx().

◆ FIXED_REGNO_P

#define FIXED_REGNO_P ( N)
Value:
((N) == FRAME_POINTER_REGNUM || (N) == HARD_FRAME_POINTER_REGNUM \
char global_regs[FIRST_PSEUDO_REGISTER]
Definition reginfo.cc:92
#define fixed_regs
Definition hard-reg-set.h:488
#define HARD_FRAME_POINTER_REGNUM
Definition rtl.h:3852
Determine whether register number N is considered a fixed register for the purpose of approximating register costs. It is desirable to replace other regs with fixed regs, to reduce need for non-fixed hard regs. A reg wins if it is either the frame pointer or designated as fixed.

Referenced by make_regs_eqv().

◆ HASH_MASK

#define HASH_MASK   (HASH_SIZE - 1)

Referenced by HASH(), and SAFE_HASH().

◆ HASH_SHIFT

#define HASH_SHIFT   5
We don't want a lot of buckets, because we rarely have very many things stored in the hash table, and a lot of buckets slows down a lot of loops that happen frequently.

Referenced by HASH(), and SAFE_HASH().

◆ HASH_SIZE

◆ REG_IN_TABLE

#define REG_IN_TABLE ( N)
Value:
static struct cse_reg_info * get_cse_reg_info(unsigned int regno)
Definition cse.cc:790
int reg_in_table
Definition cse.cc:296
Get the point at which REG was recorded in the table.

Referenced by cse_insn(), exp_equiv_p(), insert_regs(), mention_regs(), and rehash_using_reg().

◆ REG_QTY

◆ REG_TICK

#define REG_TICK ( N)
Value:
int reg_tick
Definition cse.cc:290
Get the number of times this register has been updated in this basic block.

Referenced by exp_equiv_p(), insert_regs(), invalidate_for_call(), invalidate_reg(), mention_regs(), and rehash_using_reg().

◆ REGNO_QTY_VALID_P

#define REGNO_QTY_VALID_P ( N)
Value:
(REG_QTY (N) >= 0)
#define REG_QTY(N)
Definition cse.cc:458
Determine if the quantity number for register X represents a valid index into the qty_table.

Referenced by canon_reg(), cse_insn(), cse_process_note_1(), delete_reg_equiv(), equiv_constant(), fold_rtx(), insert_regs(), insert_with_costs(), make_regs_eqv(), mention_regs(), merge_equiv_classes(), and try_back_substitute_reg().

◆ RTL_HOOKS_GEN_LOWPART

#define RTL_HOOKS_GEN_LOWPART   gen_lowpart_if_possible

◆ SUBREG_TICKED

#define SUBREG_TICKED ( N)
Value:
unsigned int subreg_ticked
Definition cse.cc:300
Get the SUBREG set at the last increment to REG_TICK (-1 if not a SUBREG).

Referenced by invalidate_for_call(), invalidate_reg(), and mention_regs().

Function Documentation

◆ add_to_set()

static void add_to_set ( vec< struct set > * sets,
rtx x,
bool is_fake_set )
inlinestatic
Add an entry containing RTL X into SETS. IS_FAKE_SET is true if X is an artifical set that has been created to describe part of an insn's effect.

References set::is_fake_set, and set::rtl.

Referenced by find_sets_in_insn().

◆ approx_reg_cost()

static int approx_reg_cost ( const_rtx x)
static
Return an estimate of the cost of the registers used in an rtx. This is mostly the number of different REG expressions in the rtx; however for some exceptions like fixed registers we use a cost of 0. If any other hard register reference occurs, return MAX_COST.

References CHEAP_REGNO, table_elt::cost, FOR_EACH_SUBRTX, GET_MODE, MAX_COST, REG_P, REGNO, and targetm.

Referenced by cse_insn(), and insert().

◆ canon_asm_operands()

static void canon_asm_operands ( rtx x,
rtx_insn * insn )
static
Subroutine of canonicalize_insn. X is an ASM_OPERANDS in INSN.

References ASM_OPERANDS_INPUT, ASM_OPERANDS_INPUT_LENGTH, canon_reg(), HARD_REGISTER_P, i, REG_P, and validate_change().

Referenced by canonicalize_insn().

◆ canon_hash()

static unsigned canon_hash ( rtx x,
machine_mode mode )
inlinestatic
Hash an rtx X for cse via hash_rtx. Stores 1 in do_not_record if any subexpression is volatile. Stores 1 in hash_arg_in_memory if X contains a mem rtx which does not have the MEM_READONLY_P flag set.

References do_not_record, hash_arg_in_memory, hash_rtx(), and table_elt::mode.

Referenced by HASH().

◆ canon_reg()

static rtx canon_reg ( rtx x,
rtx_insn * insn )
static
Canonicalize an expression: replace each register reference inside it with the "oldest" equivalent register. If INSN is nonzero validate_change is used to ensure that INSN remains valid after we make our substitution. The calls are made with IN_GROUP nonzero so apply_change_group must be called upon the outermost return from this function (unless INSN is zero). The result of apply_change_group can generally be discarded since the changes we are making are optional.

References CASE_CONST_ANY, qty_table_elem::first_reg, gen_rtx_REG(), GET_CODE, GET_RTX_FORMAT, GET_RTX_LENGTH, i, qty_table_elem::mode, qty_table, REG_QTY, REGNO, REGNO_QTY_VALID_P, regno_reg_rtx, validate_canon_reg(), XEXP, XVECEXP, and XVECLEN.

Referenced by canon_asm_operands(), canonicalize_insn(), cse_insn(), cse_process_note_1(), fold_rtx(), and validate_canon_reg().

◆ canonicalize_insn()

static void canonicalize_insn ( rtx_insn * insn,
vec< struct set > * psets )
static
Where possible, substitute every register reference in the N_SETS number of SETS in INSN with the canonical register. Register canonicalization propagatest the earliest register (i.e. one that is set before INSN) with the same value. This is a very useful, simple form of CSE, to clean up warts from expanding GIMPLE to RTL. For instance, a CONST for an address is usually expanded multiple times to loads into different registers, thus creating many subexpressions of the form: (set (reg1) (some_const)) (set (mem (... reg1 ...) (thing))) (set (reg2) (some_const)) (set (mem (... reg2 ...) (thing))) After canonicalizing, the code takes the following form: (set (reg1) (some_const)) (set (mem (... reg1 ...) (thing))) (set (reg2) (some_const)) (set (mem (... reg1 ...) (thing))) The set to reg2 is now trivially dead, and the memory reference (or address, or whatever) may be a candidate for further CSEing. In this function, the result of apply_change_group can be ignored; see canon_reg.

References apply_change_group(), CALL_INSN_FUNCTION_USAGE, CALL_P, canon_asm_operands(), canon_reg(), DEBUG_INSN_P, df_notes_rescan(), find_reg_note(), fold_rtx(), GET_CODE, i, MEM_P, NULL_RTX, PATTERN(), REG_NOTES, REG_P, REGNO, remove_note(), set::rtl, rtx_equal_p(), SET, SET_DEST, SET_SRC, set::src, validate_change(), XEXP, XVECEXP, XVECLEN, and y.

Referenced by cse_insn().

◆ check_dependence()

static bool check_dependence ( const_rtx x,
rtx exp,
machine_mode mode,
rtx addr )
static
Check whether an anti dependence exists between X and EXP. MODE and ADDR are as for canon_anti_dependence.

References canon_anti_dependence(), exp(), FOR_EACH_SUBRTX, MEM_P, and table_elt::mode.

Referenced by invalidate().

◆ check_for_label_ref()

static bool check_for_label_ref ( rtx_insn * insn)
static
Return true if the pattern of INSN uses a LABEL_REF for which there isn't a REG_LABEL_OPERAND note.

References ALL, find_reg_note(), FOR_EACH_SUBRTX, GET_CODE, INSN_UID(), JUMP_P, label_is_jump_target_p(), LABEL_P, label_ref_label(), LABEL_REF_NONLOCAL_P, and PATTERN().

Referenced by cse_extended_basic_block().

◆ compute_const_anchors()

static bool compute_const_anchors ( rtx cst,
HOST_WIDE_INT * lower_base,
HOST_WIDE_INT * lower_offs,
HOST_WIDE_INT * upper_base,
HOST_WIDE_INT * upper_offs )
static
Compute upper and lower anchors for CST. Also compute the offset of CST from these anchors/bases such that *_BASE + *_OFFS = CST. Return false iff CST is equal to an anchor.

References targetm, and UINTVAL.

Referenced by insert_const_anchors(), and try_const_anchors().

◆ count_reg_usage()

static void count_reg_usage ( rtx x,
int * counts,
rtx dest,
int incr )
static
Count the number of times registers are used (not set) in X. COUNTS is an array in which we accumulate the count, INCR is how much we count each register usage. Don't count a usage of DEST, which is the SET_DEST of a SET which contains X in its SET_SRC. This is because such a SET does not modify the liveness of DEST. DEST is set to pc_rtx for a trapping insn, or for an insn with side effects. We must then count uses of a SET_DEST regardless, because the insn can't be deleted here. Also count uses of a SET_DEST if it has been used by an earlier insn, but in that case only when incrementing and not when decrementing, effectively making setters of such a pseudo non-eliminable. This is for cases like (set (reg x) (expr)) ... (set (reg y) (expr (reg (x)))) ... (set (reg x) (expr (reg (x)))) where we can't eliminate the last insn because x is is still used, if y is unused we can eliminate the middle insn and when considering the first insn we used to eliminate it despite it being used in the last insn.

References ASM_OPERANDS_INPUT, ASM_OPERANDS_INPUT_LENGTH, CALL_INSN_FUNCTION_USAGE, CASE_CONST_ANY, cfun, count_reg_usage(), find_reg_equal_equiv_note(), gcc_unreachable, GET_CODE, GET_RTX_FORMAT, GET_RTX_LENGTH, i, insn_nothrow_p(), MEM_P, NULL_RTX, PATTERN(), pc_rtx, REG_NOTE_KIND, REG_P, REGNO, SET, SET_DEST, SET_SRC, side_effects_p(), XEXP, XVECEXP, and XVECLEN.

Referenced by count_reg_usage(), and delete_trivially_dead_insns().

◆ count_stores()

static void count_stores ( rtx x,
const_rtx set,
void * data )
static
Count the number of stores into pseudo. Callback for note_stores.

References REG_P, and REGNO.

Referenced by delete_trivially_dead_insns().

◆ cse_cc_succs()

static machine_mode cse_cc_succs ( basic_block bb,
basic_block orig_bb,
rtx cc_reg,
rtx cc_src,
bool can_change_mode )
static
BB is a basic block which finishes with CC_REG as a condition code register which is set to CC_SRC. Look through the successors of BB to find blocks which have a single predecessor (i.e., this one), and look through those blocks for an assignment to CC_REG which is equivalent to CC_SRC. CAN_CHANGE_MODE indicates whether we are permitted to change the mode of CC_SRC to a compatible mode. This returns VOIDmode if no equivalent assignments were found. Otherwise it returns the mode which CC_SRC should wind up with. ORIG_BB should be the same as BB in the outermost cse_cc_succs call, but is passed unmodified down to recursive calls in order to prevent endless recursion. The main complexity in this function is handling the mode issues. We may have more than one duplicate which we can eliminate, and we try to find a mode which will work for multiple duplicates.

References BB_END, BB_HEAD, cfun, cse_cc_succs(), cse_cfg_altered, cse_change_cc_mode_insns(), delete_insn(), delete_insn_and_edges(), EDGE_COMPLEX, EDGE_COUNT, end(), EXIT_BLOCK_PTR_FOR_FN, FOR_EACH_EDGE, gcc_assert, gen_rtx_REG(), GET_CODE, GET_MODE, i, INSN_P, insns, modes, modified_in_p(), NEXT_INSN(), NULL_RTX, PUT_MODE(), REG_P, reg_set_p(), REGNO, rtx_equal_p(), SET_DEST, SET_SRC, single_set(), basic_block_def::succs, targetm, and XEXP.

Referenced by cse_cc_succs(), and cse_condition_code_reg().

◆ cse_change_cc_mode()

static void cse_change_cc_mode ( subrtx_ptr_iterator::array_type & array,
rtx * loc,
rtx_insn * insn,
rtx newreg )
static
If LOC contains references to NEWREG in a different mode, change them to use NEWREG instead.

References FOR_EACH_SUBRTX_PTR, GET_MODE, REG_P, REGNO, and validate_change().

Referenced by cse_change_cc_mode_insn().

◆ cse_change_cc_mode_insn()

static void cse_change_cc_mode_insn ( rtx_insn * insn,
rtx newreg )
static
Change the mode of any reference to the register REGNO (NEWREG) to GET_MODE (NEWREG) in INSN.

References apply_change_group(), cse_change_cc_mode(), gcc_assert, INSN_P, PATTERN(), and REG_NOTES.

Referenced by cse_change_cc_mode_insns(), and cse_condition_code_reg().

◆ cse_change_cc_mode_insns()

static void cse_change_cc_mode_insns ( rtx_insn * start,
rtx_insn * end,
rtx newreg )
static
Change the mode of any reference to the register REGNO (NEWREG) to GET_MODE (NEWREG), starting at START. Stop before END. Stop at any instruction which modifies NEWREG.

References cse_change_cc_mode_insn(), end(), INSN_P, NEXT_INSN(), and reg_set_p().

Referenced by cse_cc_succs(), and cse_condition_code_reg().

◆ cse_condition_code_reg()

static void cse_condition_code_reg ( void )
static
If we have a fixed condition code register (or two), walk through the instructions and try to eliminate duplicate assignments.

References BB_END, BB_HEAD, cfun, cse_cc_succs(), cse_change_cc_mode_insn(), cse_change_cc_mode_insns(), FOR_EACH_BB_FN, gcc_assert, gen_rtx_REG(), GET_MODE, INSN_P, INVALID_REGNUM, JUMP_P, modified_between_p(), NEXT_INSN(), NULL, NULL_RTX, PATTERN(), PREV_INSN(), REG_P, reg_referenced_p(), reg_set_p(), REGNO, SET_DEST, SET_SRC, single_set(), and targetm.

Referenced by rest_of_handle_cse2().

◆ cse_dump_path()

static void cse_dump_path ( struct cse_basic_block_data * data,
int nsets,
FILE * f )
static
Dump the path in DATA to file F. NSETS is the number of sets in the path.

References fputc().

Referenced by cse_main().

◆ cse_extended_basic_block()

◆ cse_find_path()

static bool cse_find_path ( basic_block first_bb,
struct cse_basic_block_data * data,
int follow_jumps )
static
Find a path in the CFG, starting with FIRST_BB to perform CSE on. DATA is a pointer to a struct cse_basic_block_data, that is used to describe the path. It is filled with a queue of basic blocks, starting with FIRST_BB and following a trace through the CFG. If all paths starting at FIRST_BB have been followed, or no new path starting at FIRST_BB can be constructed, this function returns FALSE. Otherwise, DATA->path is filled and the function returns TRUE indicating that a path to follow was found. If FOLLOW_JUMPS is false, the maximum path length is 1 and the only block in the path will be FIRST_BB.

References any_condjump_p(), BB_END, bitmap_bit_p, bitmap_set_bit, BRANCH_EDGE, cfun, cse_visited_basic_blocks, EDGE_COUNT, EXIT_BLOCK_PTR_FOR_FN, FALLTHRU_EDGE, find_edge(), follow_jumps(), gcc_assert, basic_block_def::index, NULL, single_pred_p(), single_succ_edge(), single_succ_p(), and basic_block_def::succs.

Referenced by cse_main().

◆ cse_insn()

static void cse_insn ( rtx_insn * insn)
static
Main function of CSE. First simplify sources and addresses of all assignments in the instruction, using previously-computed equivalents values. Then install the new sources and destinations in the table of available values.

References alias_set_subset_of(), apply_change_group(), approx_reg_cost(), as_a(), BITS_PER_WORD, CALL_INSN_FUNCTION_USAGE, CALL_P, can_throw_internal(), canon_reg(), canonicalize_insn(), cfun, condjump_p(), CONST_INT_P, const_vec_duplicate_p(), CONSTANT_P, copy_rtx(), COST, table_elt::cost, crtl, cse_cfg_altered, cse_jumps_altered, delete_insn_and_edges(), df_notes_rescan(), do_not_record, emit_jump_insn_before(), END_REGNO(), table_elt::exp, exp_equiv_p(), find_reg_note(), find_sets_in_insn(), qty_table_elem::first_reg, table_elt::first_same_value, FLOAT_MODE_P, flush_hash_table(), fold_rtx(), FOR_EACH_WIDER_MODE, force_const_mem(), GEN_INT, gen_lowpart, gen_rtx_REG(), GET_CODE, GET_MODE, GET_MODE_CLASS, GET_MODE_INNER, GET_MODE_PRECISION(), GET_MODE_SIZE(), GET_RTX_CLASS, HASH(), hash_arg_in_memory, HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1, HOST_WIDE_INT_M1, HOST_WIDE_INT_M1U, i, table_elt::in_memory, insert(), insert_const_anchors(), insert_regs(), INSN_CODE, insn_nothrow_p(), INTVAL, invalidate(), invalidate_dest(), invalidate_for_call(), invalidate_from_clobbers(), invalidate_from_sets_and_clobbers(), invalidate_memory(), is_a(), is_int_mode(), JUMP_LABEL, known_ge, LABEL_NUSES, LABEL_REF_NONLOCAL_P, load_extend_op(), lookup(), MAX_COST, MEM_ALIAS_SET, MEM_EXPR, MEM_P, MEM_READONLY_P, mention_regs(), merge_equiv_classes(), qty_table_elem::mode, table_elt::mode, new_mode(), table_elt::next_same_value, NULL, NULL_RTX, paradoxical_subreg_p(), partial_subreg_p(), PATTERN(), pc_rtx, preferable(), table_elt::prev_same_value, PUT_CODE, PUT_MODE(), qty_table, refs_same_for_tbaa_p(), REG_IN_TABLE, REG_NOTES, REG_P, REG_QTY, table_elt::regcost, REGNO, REGNO_QTY_VALID_P, regno_reg_rtx, rehash_using_reg(), table_elt::related_value, remove_invalid_refs(), remove_note(), opt_mode< T >::require(), RTL_CONST_OR_PURE_CALL_P, RTX_AUTOINC, rtx_equal_p(), SCALAR_INT_MODE_P, SET_DEST, SET_SRC, set_unique_reg_note(), shift, side_effects_p(), simplify_gen_subreg(), stack_pointer_rtx, subreg_lowpart_offset(), SUBREG_REG, targetm, this_insn, trunc_int_for_mode(), try_back_substitute_reg(), try_const_anchors(), use_related_value(), validate_change(), validate_unshare_change(), XEXP, XVECEXP, XVECLEN, and y.

Referenced by cse_extended_basic_block().

◆ cse_main()

static int cse_main ( rtx_insn * f,
int nregs )
static

◆ cse_prescan_path()

static void cse_prescan_path ( struct cse_basic_block_data * data)
static
Scan to the end of the path described by DATA. Return an estimate of the total number of SETs of all insns in the path.

References FOR_BB_INSNS, GET_CODE, INSN_P, PATTERN(), and XVECLEN.

Referenced by cse_main().

◆ cse_process_note()

static rtx cse_process_note ( rtx x)
static
Process X, part of the REG_NOTES of an insn. Replace any registers in it with either an equivalent constant or the canonical form of the register. Only replace addresses if the containing MEM remains valid.

References cse_process_note_1(), NULL, NULL_RTX, and simplify_replace_fn_rtx().

Referenced by cse_extended_basic_block(), and cse_process_note_1().

◆ cse_process_note_1()

static rtx cse_process_note_1 ( rtx x,
const_rtx ,
void *  )
static
A simplify_replace_fn_rtx callback for cse_process_note. Process X, part of the REG_NOTES of an insn. Replace any registers with either an equivalent constant or the canonical form of the register. Only replace addresses if the containing MEM remains valid. Return the replacement for X, or null if it should be simplified recursively.

References canon_reg(), qty_table_elem::const_rtx, CONSTANT_P, copy_rtx(), cse_process_note(), gen_lowpart, GET_MODE, i, MEM_P, NULL, NULL_RTX, qty_table, REG_P, REG_QTY, REGNO, REGNO_QTY_VALID_P, validate_change(), and XEXP.

Referenced by cse_process_note().

◆ delete_reg_equiv()

static void delete_reg_equiv ( unsigned int reg)
static

◆ delete_trivially_dead_insns()

int delete_trivially_dead_insns ( rtx_insn * insns,
int nreg )
Scan all the insns and delete any that are dead; i.e., they store a register that is never used or they copy a register to itself. This is used to remove insns made obviously dead by cse, loop or other optimizations. It improves the heuristics in loop since it won't try to move dead invariants out of loops or make givs for dead quantities. The remaining passes of the compilation are also sped up.

References asm_noperands(), count_reg_usage(), count_stores(), cse_cfg_altered, dbg_cnt(), DEBUG_BIND_INSN_P, DEBUG_EXPR_TREE_DECL, DEBUG_INSN_P, DEBUG_MARKER_INSN_P, delete_insn_and_edges(), df_insn_rescan(), dump_file, emit_debug_insn_before(), free(), gen_rtx_UNKNOWN_VAR_LOC, gen_rtx_VAR_LOCATION(), get_last_insn(), GET_MODE, insn_live_p(), INSN_P, INSN_VAR_LOCATION_DECL, INSN_VAR_LOCATION_LOC, insns, is_dead_debug_insn(), is_dead_reg(), make_debug_expr_from_rtl(), MAY_HAVE_DEBUG_BIND_INSNS, NEXT_INSN(), note_stores(), NULL, NULL_RTX, PATTERN(), pic_offset_table_rtx, PREV_INSN(), REGNO, reload_completed, replace_dead_reg(), replacements, SET_DEST, SET_SRC, side_effects_p(), simplify_replace_fn_rtx(), single_set(), timevar_pop(), timevar_push(), TREE_VISITED, and VAR_INIT_STATUS_INITIALIZED.

Referenced by cleanup_cfg(), fwprop_done(), ira(), rest_of_handle_cse2(), and rest_of_handle_cse_after_global_opts().

◆ dump_class()

DEBUG_FUNCTION void dump_class ( struct table_elt * classp)
extern
Dump the expressions in the equivalence class indicated by CLASSP. This function is used only for debugging.

References table_elt::exp, table_elt::first_same_value, table_elt::next_same_value, and print_rtl().

◆ equiv_constant()

◆ exp_equiv_p()

bool exp_equiv_p ( const_rtx x,
const_rtx y,
int validate,
bool for_gcse )

◆ find_comparison_args()

static enum rtx_code find_comparison_args ( enum rtx_code code,
rtx * parg1,
rtx * parg2,
machine_mode * pmode1,
machine_mode * pmode2 )
static
Given an operation (CODE, *PARG1, *PARG2), where code is a comparison operation (EQ, NE, GT, etc.), follow it back through the hash table and what values are being compared. *PARG1 and *PARG2 are updated to contain the rtx representing the values actually being compared. For example, if *PARG1 was (reg:CC CC_REG) and *PARG2 was (const_int 0), *PARG1 and *PARG2 will be set to the objects that were compared to produce (reg:CC CC_REG). The return value is the comparison operator and is either the code of A or the code corresponding to the inverse of the comparison.

References COMPARISON_P, CONST0_RTX, const0_rtx, table_elt::exp, exp_equiv_p(), table_elt::first_same_value, fold_rtx(), GET_CODE, GET_MODE, GET_MODE_CLASS, table_elt::is_const, lookup(), table_elt::next_same_value, NULL, REAL_VALUE_NEGATIVE, REAL_VALUE_TYPE, reversed_comparison_code(), rtx_addr_can_trap_p(), SAFE_HASH(), SCALAR_FLOAT_MODE_P, STORE_FLAG_VALUE, val_signbit_known_set_p(), visited, and XEXP.

Referenced by fold_rtx(), and record_jump_equiv().

◆ find_reg_offset_for_const()

static rtx find_reg_offset_for_const ( struct table_elt * anchor_elt,
HOST_WIDE_INT offs,
unsigned * old )
static
We need to express ANCHOR_ELT->exp + OFFS. Walk the equivalence list of ANCHOR_ELT and see if offsetting any of the entries by OFFS would create a valid expression. Return the cheapest and oldest of such expressions. In *OLD, return how old the resulting expression is compared to the other equivalent expressions.

References CHEAPER, table_elt::exp, exp_equiv_p(), table_elt::first_same_value, GET_CODE, GET_MODE, IN_RANGE, INTVAL, table_elt::next_same_value, NULL, NULL_RTX, plus_constant(), REG_P, targetm, and XEXP.

Referenced by try_const_anchors().

◆ find_sets_in_insn()

static int find_sets_in_insn ( rtx_insn * insn,
vec< struct set > * psets )
static
Record all the SETs in this instruction into SETS_PTR, and return the number of recorded sets.

References add_to_set(), CONST_VECTOR_ELT, const_vector_encoded_nelts(), gcc_assert, GET_CODE, GET_MODE, GET_MODE_CLASS, GET_MODE_NUNITS(), i, known_eq, PATTERN(), pc_rtx, SET, SET_DEST, SET_SRC, simplify_gen_vec_select(), set::src, SUBREG_P, XVECEXP, XVECLEN, and y.

Referenced by cse_insn().

◆ fixed_base_plus_p()

static bool fixed_base_plus_p ( rtx x)
static
Nonzero if X has the form (PLUS frame-pointer integer).

References arg_pointer_rtx, CONST_INT_P, fixed_base_plus_p(), fixed_regs, frame_pointer_rtx, GET_CODE, hard_frame_pointer_rtx, and XEXP.

Referenced by fixed_base_plus_p(), and insert_with_costs().

◆ flush_hash_table()

static void flush_hash_table ( void )
static
Flush the entire hash table.

References table_elt::exp, HASH_SIZE, i, invalidate(), REG_P, remove_from_table(), and table.

Referenced by cse_extended_basic_block(), and cse_insn().

◆ fold_rtx()

static rtx fold_rtx ( rtx x,
rtx_insn * insn )
static
If X is a nontrivial arithmetic operation on an argument for which a constant value can be determined, return the result of operating on that value, as a constant. Otherwise, return X, possibly with one or more operands changed to a forward-propagated constant. If X is a register whose contents are known, we do NOT return those contents here; equiv_constant is called to perform that task. For SUBREGs and MEMs, we do that both here and in equiv_constant. INSN is the insn that we may be modifying. If it is 0, make a copy of X before modifying it.

References apply_change_group(), ASM_OPERANDS_INPUT, ASM_OPERANDS_INPUT_LENGTH, canon_reg(), canonicalize_change_group(), CASE_CONST_ANY, changed, qty_table_elem::comparison_code, qty_table_elem::comparison_const, comparison_dominates_p(), qty_table_elem::comparison_qty, CONST0_RTX, const0_rtx, const_double_from_real_value(), CONST_INT_P, const_true_rtx, CONSTANT_P, copy_rtx(), COST, table_elt::cost, COST_IN, equiv_constant(), table_elt::exp, exp_equiv_p(), false_rtx, find_comparison_args(), table_elt::first_same_value, FLOAT_MODE_P, fold_rtx(), GEN_INT, gen_int_shift_amount(), GET_CODE, GET_MODE, GET_MODE_CLASS, GET_MODE_UNIT_BITSIZE, GET_MODE_UNIT_PRECISION, GET_RTX_CLASS, GET_RTX_FORMAT, GET_RTX_LENGTH, HAVE_POST_DECREMENT, HAVE_POST_INCREMENT, HAVE_PRE_DECREMENT, HAVE_PRE_INCREMENT, HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1, i, INTVAL, label_ref_label(), lookup(), lookup_as_function(), lowpart_subreg(), qty_table_elem::mode, table_elt::mode, table_elt::next_same_value, NO_FUNCTION_CSE, NULL, NULL_RTX, plus_constant(), poly_int_rtx_p(), pow2p_hwi(), qty_table, reg_mentioned_p(), REG_P, REG_QTY, REGNO, REGNO_QTY_VALID_P, reverse_condition(), RTX_BIN_ARITH, RTX_BITFIELD_OPS, RTX_COMM_ARITH, RTX_COMM_COMPARE, RTX_COMPARE, rtx_equal_p(), RTX_OBJ, RTX_TERNARY, RTX_UNARY, SAFE_HASH(), SCALAR_FLOAT_MODE_P, SHIFT_COUNT_TRUNCATED, side_effects_p(), simplify_binary_operation(), simplify_gen_binary(), simplify_relational_operation(), simplify_ternary_operation(), simplify_unary_operation(), true_rtx, validate_change(), validate_unshare_change(), vec_series_lowpart_p(), VECTOR_MODE_P, XEXP, and y.

Referenced by canonicalize_insn(), cse_insn(), find_comparison_args(), fold_rtx(), and record_jump_equiv().

◆ get_cse_reg_info()

static struct cse_reg_info * get_cse_reg_info ( unsigned int regno)
inlinestatic
Find a cse_reg_info entry for REGNO.

References cse_reg_info_table, cse_reg_info_timestamp, get_cse_reg_info_1(), and cse_reg_info::timestamp.

◆ get_cse_reg_info_1()

static void get_cse_reg_info_1 ( unsigned int regno)
static
Given REGNO, initialize the cse_reg_info entry for REGNO.

References cse_reg_info_table, and cse_reg_info_timestamp.

Referenced by get_cse_reg_info().

◆ HASH()

static unsigned HASH ( rtx x,
machine_mode mode )
inlinestatic
Compute hash code of X in mode M. Special-case case where X is a pseudo register (hard registers may require `do_not_record' to be set).

References canon_hash(), HASH_MASK, HASH_SHIFT, REG_P, REG_QTY, and REGNO.

Referenced by cse_insn(), insert_const_anchor(), invalidate_reg(), merge_equiv_classes(), record_jump_cond(), and try_const_anchors().

◆ hash_rtx()

unsigned hash_rtx ( const_rtx x,
machine_mode mode,
int * do_not_record_p,
int * hash_arg_in_memory_p,
bool have_reg_qty,
hash_rtx_callback_function cb )
Hash an rtx. We are careful to make sure the value is never negative. Equivalent registers hash identically. MODE is used in hashing for CONST_INTs only; otherwise the mode of X is used. Store 1 in DO_NOT_RECORD_P if any subexpression is volatile. If HASH_ARG_IN_MEMORY_P is not NULL, store 1 in it if X contains a MEM rtx which does not have the MEM_READONLY_P flag set. Note that cse_insn knows that the hash code of a MEM expression is just (int) MEM plus the hash code of the address. Call CB on each rtx if CB is not NULL. When the callback returns true, we continue with the new rtx.

References inchash::hash::add_int(), inchash::hash::add_wide_int(), arg_pointer_rtx, ASM_OPERANDS_INPUT, ASM_OPERANDS_INPUT_CONSTRAINT, ASM_OPERANDS_INPUT_LENGTH, ASM_OPERANDS_OUTPUT_CONSTRAINT, ASM_OPERANDS_OUTPUT_IDX, ASM_OPERANDS_TEMPLATE, CODE_LABEL_NUMBER, CONST_DOUBLE_HIGH, CONST_DOUBLE_LOW, CONST_DOUBLE_REAL_VALUE, CONST_FIXED_VALUE, CONST_POLY_INT_COEFFS, CONST_VECTOR_ENCODED_ELT, const_vector_encoded_nelts(), CONST_WIDE_INT_ELT, CONST_WIDE_INT_NUNITS, inchash::hash::end(), fixed_hash(), fixed_regs, frame_pointer_rtx, gcc_unreachable, GET_CODE, GET_MODE, GET_MODE_CLASS, GET_RTX_FORMAT, GET_RTX_LENGTH, global_regs, hard_frame_pointer_rtx, hash_rtx(), hash_rtx_string(), i, INTVAL, label_ref_label(), MEM_P, MEM_READONLY_P, MEM_VOLATILE_P, table_elt::mode, NULL, NUM_POLY_INT_COEFFS, pic_offset_table_rtx, real_hash(), REG_P, REG_QTY, REGNO, reload_completed, stack_pointer_rtx, SUBREG_BYTE, SUBREG_REG, TARGET_SUPPORTS_WIDE_INT, targetm, XEXP, XINT, XLOC, XSTR, XVECEXP, and XVECLEN.

Referenced by canon_hash(), invariant_group_base_hasher::hash(), pre_ldst_expr_hasher::hash(), st_expr_hasher::hash(), hash_expr(), hash_expr(), hash_invariant_expr_1(), hash_rtx(), ldst_entry(), safe_hash(), st_expr_entry(), and temp_slot_address_compute_hash().

◆ hash_rtx_string()

static unsigned hash_rtx_string ( const char * ps)
inlinestatic
Hash a string. Just add its bytes up.

Referenced by hash_rtx().

◆ have_eh_succ_edges()

static bool have_eh_succ_edges ( basic_block bb)
static
Return true if BB has exception handling successor edges.

References FOR_EACH_EDGE, and basic_block_def::succs.

Referenced by cse_extended_basic_block().

◆ init_cse_reg_info()

static void init_cse_reg_info ( unsigned int nregs)
static

◆ insert() [1/2]

static struct table_elt * insert ( rtx x,
struct table_elt * classp,
unsigned int hash,
machine_mode mode )
static
Wrap insert_with_costs by passing the default costs.

References approx_reg_cost(), COST, insert_with_costs(), and table_elt::mode.

◆ insert() [2/2]

◆ insert_const_anchor()

static void insert_const_anchor ( HOST_WIDE_INT anchor,
rtx reg,
HOST_WIDE_INT offs,
machine_mode mode )
static
Insert the equivalence between ANCHOR and (REG + OFF) in mode MODE.

References COST, exp(), gen_int_mode(), HASH(), insert(), insert_with_costs(), lookup(), mention_regs(), table_elt::mode, NULL, and plus_constant().

Referenced by insert_const_anchors().

◆ insert_const_anchors()

static void insert_const_anchors ( rtx reg,
rtx cst,
machine_mode mode )
static
The constant CST is equivalent to the register REG. Create equivalences between the two anchors of CST and the corresponding register-offset expressions using REG.

References compute_const_anchors(), insert_const_anchor(), and table_elt::mode.

Referenced by cse_insn().

◆ insert_regs()

static bool insert_regs ( rtx x,
struct table_elt * classp,
bool modified )
static
Update the register quantities for inserting X into the hash table with a value equivalent to CLASSP. (If the class does not contain a REG, it is irrelevant.) If MODIFIED is true, X is a destination; it is being modified. Note that delete_reg_equiv should be called on a register before insert_regs is done on that register with MODIFIED != 0. True value means that elements of reg_qty have changed so X's hash code may be different.

References table_elt::exp, table_elt::first_same_value, gcc_assert, GET_CODE, GET_MODE, insert_regs(), make_new_qty(), make_regs_eqv(), mention_regs(), qty_table_elem::mode, table_elt::next_same_value, NULL, qty_table, REG_IN_TABLE, REG_P, REG_QTY, REG_TICK, REGNO, REGNO_QTY_VALID_P, and SUBREG_REG.

Referenced by cse_insn(), insert_regs(), mention_regs(), merge_equiv_classes(), and record_jump_cond().

◆ insert_with_costs() [1/2]

static struct table_elt * insert_with_costs ( rtx x,
struct table_elt * classp,
unsigned int hash,
machine_mode mode,
int cost,
int reg_cost )
static
Insert X in the hash table, assuming HASH is its hash code and CLASSP is an element of the class it should go in (or 0 if a new class should be made). COST is the code of X and reg_cost is the cost of registers in X. It is inserted at the proper position to keep the class in the order cheapest first. MODE is the machine-mode of X, or if X is an integer constant with VOIDmode then MODE is the mode with which X will be used. For elements of equal cheapness, the most recent one goes in front, except that the first element in the list remains first unless a cheaper element is added. The order of pseudo-registers does not matter, as canon_reg will be called to find the cheapest when a register is retrieved from the table. The in_memory field in the hash table element is set to 0. The caller must set it nonzero if appropriate. You should call insert_regs (X, CLASSP, MODIFY) before calling here, and if insert_regs returns a nonzero value you must then recompute its hash code before calling here. If necessary, update table showing constant values of quantities.

References add_to_hard_reg_set(), table_elt::canon_exp, CHEAPER, qty_table_elem::const_insn, qty_table_elem::const_rtx, CONSTANT_P, table_elt::cost, table_elt::exp, table_elt::first_same_value, fixed_base_plus_p(), free_element_chain, gcc_assert, gen_lowpart, GET_CODE, GET_MODE, get_related_value(), hard_regs_in_table, table_elt::in_memory, insert(), table_elt::is_const, lookup(), qty_table_elem::mode, table_elt::mode, table_elt::next_same_hash, table_elt::next_same_value, NULL, NULL_RTX, table_elt::prev_same_hash, table_elt::prev_same_value, qty_table, REG_P, REG_QTY, table_elt::regcost, REGNO, REGNO_QTY_VALID_P, table_elt::related_value, SAFE_HASH(), table, and this_insn.

◆ insert_with_costs() [2/2]

static struct table_elt * insert_with_costs ( rtx ,
struct table_elt * ,
unsigned ,
machine_mode ,
int ,
int  )
static

Referenced by insert(), and insert_const_anchor().

◆ insn_live_p()

static bool insn_live_p ( rtx_insn * insn,
int * counts )
static

◆ invalidate()

static void invalidate ( rtx x,
machine_mode full_mode )
static
Remove from the hash table, or mark as invalid, all expressions whose values could be altered by storing in X. X is a register, a subreg, or a memory reference with nonvarying address (because, when a memory reference with a varying address is stored in, all memory references are removed by invalidate_memory so specific invalidation is superfluous). FULL_MODE, if not VOIDmode, indicates that this much should be invalidated instead of just the amount indicated by the mode of X. This is only used for bitfield stores into memory. A nonvarying address may be just a register or just a symbol reference, or it may be either of those plus a numeric offset.

References table_elt::canon_exp, canon_rtx(), check_dependence(), table_elt::exp, gcc_unreachable, get_addr(), GET_CODE, GET_MODE, HASH_SIZE, i, table_elt::in_memory, invalidate(), invalidate_reg(), table_elt::next_same_hash, remove_from_table(), SUBREG_REG, table, XEXP, XVECEXP, and XVECLEN.

Referenced by ipa_polymorphic_call_context::combine_with(), cse_extended_basic_block(), cse_insn(), flush_hash_table(), invalidate(), invalidate_dest(), invalidate_from_clobbers(), invalidate_from_sets_and_clobbers(), and move2add_note_store().

◆ invalidate_dest()

static void invalidate_dest ( rtx dest)
static
Invalidate DEST. Used when DEST is not going to be added into the hash table for some reason, e.g. do_not_record flagged on it.

References GET_CODE, GET_MODE, invalidate(), MEM_P, REG_P, and XEXP.

Referenced by cse_insn().

◆ invalidate_for_call()

static void invalidate_for_call ( rtx_insn * insn)
static

◆ invalidate_from_clobbers()

static void invalidate_from_clobbers ( rtx_insn * insn)
static
Perform invalidation on the basis of everything about INSN, except for invalidating the actual places that are SET in it. This includes the places CLOBBERed, and anything that might alias with something that is SET or CLOBBERed.

References GET_CODE, GET_MODE, i, invalidate(), MEM_P, PATTERN(), REG_P, XEXP, XVECEXP, XVECLEN, and y.

Referenced by cse_insn().

◆ invalidate_from_sets_and_clobbers()

static void invalidate_from_sets_and_clobbers ( rtx_insn * insn)
static
Perform invalidation on the basis of everything about INSN. This includes the places CLOBBERed, and anything that might alias with something that is SET or CLOBBERed.

References CALL_INSN_FUNCTION_USAGE, CALL_P, GET_CODE, GET_MODE, i, invalidate(), PATTERN(), REG_P, SET, SET_DEST, SET_SRC, XEXP, XVECEXP, XVECLEN, and y.

Referenced by cse_insn().

◆ invalidate_memory()

static void invalidate_memory ( void )
static
Remove from the hash table all expressions that reference memory.

References HASH_SIZE, i, table_elt::in_memory, table_elt::next_same_hash, remove_from_table(), and table.

Referenced by cse_insn().

◆ invalidate_reg()

static void invalidate_reg ( rtx x)
static
Remove from the hash table, or mark as invalid, all expressions whose values could be altered by storing in register X.

References CLEAR_HARD_REG_BIT, delete_reg_equiv(), END_REGNO(), table_elt::exp, gcc_assert, GET_CODE, GET_MODE, hard_regs_in_table, HASH(), HASH_SIZE, table_elt::next_same_hash, REG_P, REG_TICK, REGNO, remove_from_table(), remove_pseudo_from_table(), SUBREG_TICKED, table, and TEST_HARD_REG_BIT.

Referenced by invalidate().

◆ is_dead_debug_insn()

static bool is_dead_debug_insn ( const_rtx pat,
int * counts,
rtx * replacements,
bool * seen_repl )
static
Return if DEBUG_INSN pattern PAT needs to be reset because some dead pseudo doesn't have a replacement. COUNTS[X] is zero if register X is dead and REPLACEMENTS[X] is null if it has no replacemenet. Set *SEEN_REPL to true if we see a dead register that does have a replacement.

References FOR_EACH_SUBRTX, is_dead_reg(), NULL_RTX, REGNO, and replacements.

Referenced by delete_trivially_dead_insns().

◆ is_dead_reg()

static bool is_dead_reg ( const_rtx x,
int * counts )
inlinestatic
Return true if X is a dead register.

References REG_P, and REGNO.

Referenced by delete_trivially_dead_insns(), is_dead_debug_insn(), and set_live_p().

◆ lookup() [1/2]

static struct table_elt * lookup ( rtx x,
unsigned int hash,
machine_mode mode )
static
Look up X in the hash table and return its table element, or 0 if X is not in the table. MODE is the machine-mode of X, or if X is an integer constant with VOIDmode then MODE is the mode with which X will be used. Here we are satisfied to find an expression whose tree structure looks like X.

References table_elt::exp, exp_equiv_p(), table_elt::mode, table_elt::next_same_hash, REG_P, and table.

◆ lookup() [2/2]

◆ lookup_as_function()

static rtx lookup_as_function ( rtx x,
enum rtx_code code )
static
Look for an expression equivalent to X and with code CODE. If one is found, return that expression.

References table_elt::exp, exp_equiv_p(), table_elt::first_same_value, GET_CODE, GET_MODE, lookup(), table_elt::next_same_value, and SAFE_HASH().

Referenced by equiv_constant(), and fold_rtx().

◆ lookup_for_remove() [1/2]

static struct table_elt * lookup_for_remove ( rtx x,
unsigned int hash,
machine_mode mode )
static
Like `lookup' but don't care whether the table element uses invalid regs. Also ignore discrepancies in the machine mode of a register.

References table_elt::exp, exp_equiv_p(), table_elt::mode, table_elt::next_same_hash, REG_P, REGNO, and table.

◆ lookup_for_remove() [2/2]

static struct table_elt * lookup_for_remove ( rtx ,
unsigned ,
machine_mode  )
static

◆ make_new_qty()

static void make_new_qty ( unsigned int reg,
machine_mode mode )
static
Say that register REG contains a quantity in mode MODE not in any register before and initialize that quantity.

References qty_table_elem::comparison_code, qty_table_elem::const_insn, qty_table_elem::const_rtx, qty_table_elem::first_reg, gcc_assert, qty_table_elem::last_reg, max_qty, qty_table_elem::mode, reg_eqv_elem::next, next_qty, NULL, reg_eqv_elem::prev, qty_table, reg_eqv_table, and REG_QTY.

Referenced by insert_regs().

◆ make_pass_cse()

rtl_opt_pass * make_pass_cse ( gcc::context * ctxt)

◆ make_pass_cse2()

rtl_opt_pass * make_pass_cse2 ( gcc::context * ctxt)

◆ make_pass_cse_after_global_opts()

rtl_opt_pass * make_pass_cse_after_global_opts ( gcc::context * ctxt)

◆ make_regs_eqv()

static void make_regs_eqv ( unsigned int new_reg,
unsigned int old_reg )
static
Make reg NEW equivalent to reg OLD. OLD is not changing; NEW is.

References bitmap_bit_p, cse_ebb_live_in, cse_ebb_live_out, qty_table_elem::first_reg, FIXED_REGNO_P, gcc_assert, qty_table_elem::last_reg, qty_table, reg_eqv_table, REG_QTY, and REGNO_QTY_VALID_P.

Referenced by insert_regs().

◆ mention_regs()

static bool mention_regs ( rtx x)
static
Remove any invalid expressions from the hash table that refer to any of the registers contained in expression X. Make sure that newly inserted references to those registers as subexpressions will be considered valid. mention_regs is not called when a register itself is being stored in the table. Return true if we have done something that may have changed the hash code of X.

References changed, COMPARISON_P, END_REGNO(), GET_CODE, GET_MODE, GET_RTX_FORMAT, GET_RTX_LENGTH, i, insert_regs(), mention_regs(), NULL, REG_IN_TABLE, REG_P, REG_TICK, REGNO, REGNO_QTY_VALID_P, rehash_using_reg(), remove_invalid_refs(), remove_invalid_subreg_refs(), SUBREG_BYTE, SUBREG_REG, SUBREG_TICKED, XEXP, XVECEXP, and XVECLEN.

Referenced by cse_insn(), insert_const_anchor(), insert_regs(), and mention_regs().

◆ merge_equiv_classes()

static void merge_equiv_classes ( struct table_elt * class1,
struct table_elt * class2 )
static
Given two equivalence classes, CLASS1 and CLASS2, put all the entries from CLASS2 into CLASS1. This is done when we have reached an insn which makes the two classes equivalent. CLASS1 will be the surviving class; CLASS2 should not be used after this call. Any invalid entries in CLASS2 will not be copied.

References table_elt::cost, delete_reg_equiv(), exp(), table_elt::exp, exp_equiv_p(), table_elt::first_same_value, GET_CODE, HASH(), hash_arg_in_memory, table_elt::in_memory, insert(), insert_regs(), MAX_COST, table_elt::mode, table_elt::next_same_value, REG_P, REGNO, REGNO_QTY_VALID_P, rehash_using_reg(), remove_from_table(), and remove_pseudo_from_table().

Referenced by cse_insn(), and record_jump_cond().

◆ new_basic_block()

static void new_basic_block ( void )
static
Clear the hash table and initialize each register with its own quantity, for a new basic block.

References CLEAR_HARD_REG_SET, cse_reg_info_timestamp, free_element_chain, hard_regs_in_table, HASH_SIZE, i, last, next_qty, NULL, and table.

Referenced by cse_extended_basic_block().

◆ notreg_cost()

static int notreg_cost ( rtx x,
machine_mode mode,
enum rtx_code outer,
int opno )
static
Internal function, to compute cost when X is not a register; called from COST macro to keep it simple.

References GET_CODE, GET_MODE, GET_MODE_SIZE(), is_int_mode(), table_elt::mode, optimize_this_for_speed_p, REG_P, rtx_cost(), subreg_lowpart_p(), SUBREG_REG, and TRULY_NOOP_TRUNCATION_MODES_P.

◆ preferable()

static int preferable ( int cost_a,
int regcost_a,
int cost_b,
int regcost_b )
static
Return a negative value if an rtx A, whose costs are given by COST_A and REGCOST_A, is more desirable than an rtx B. Return a positive value if A is less desirable, or 0 if the two are equally good.

References MAX_COST.

Referenced by cse_insn().

◆ record_jump_cond()

◆ record_jump_cond_subreg()

static rtx record_jump_cond_subreg ( machine_mode mode,
rtx op )
static
Yet another form of subreg creation. In this case, we want something in MODE, and we should assume OP has MODE iff it is naturally modeless.

References GET_MODE, lowpart_subreg(), and table_elt::mode.

Referenced by record_jump_cond().

◆ record_jump_equiv()

static void record_jump_equiv ( rtx_insn * insn,
bool taken )
static
Given INSN, a jump insn, TAKEN indicates if we are following the "taken" branch. In certain cases, this can cause us to add an equivalence. For example, if we are following the taken case of if (i == 2) we can add the fact that `i' and '2' are now equivalent. In any case, we can record that this comparison was passed. If the same comparison is seen later, we will know its value.

References any_condjump_p(), find_comparison_args(), fold_rtx(), gcc_assert, GET_CODE, table_elt::mode, NULL_RTX, pc_rtx, pc_set(), record_jump_cond(), reversed_comparison_code_parts(), SET_SRC, and XEXP.

Referenced by cse_extended_basic_block().

◆ rehash_using_reg()

static void rehash_using_reg ( rtx x)
static
Recompute the hash codes of any valid entries in the hash table that reference X, if X is a register, or SUBREG_REG (X) if X is a SUBREG. This is called when we make a jump equivalence.

References table_elt::exp, exp_equiv_p(), GET_CODE, HASH_SIZE, i, table_elt::mode, table_elt::next_same_hash, table_elt::prev_same_hash, REG_IN_TABLE, reg_mentioned_p(), REG_P, REG_TICK, REGNO, SAFE_HASH(), SUBREG_REG, and table.

Referenced by cse_insn(), mention_regs(), merge_equiv_classes(), and record_jump_cond().

◆ remove_from_table() [1/2]

◆ remove_from_table() [2/2]

static void remove_from_table ( struct table_elt * elt,
unsigned int hash )
static
Look in or update the hash table.
Remove table element ELT from use in the table. HASH is its hash code, made using the HASH macro. It's an argument because often that is known in advance and we save much time not recomputing it.

References table_elt::first_same_value, free_element_chain, HASH_SIZE, table_elt::next_same_hash, table_elt::next_same_value, table_elt::prev_same_hash, table_elt::prev_same_value, table_elt::related_value, and table.

◆ remove_invalid_refs()

static void remove_invalid_refs ( unsigned int regno)
static
Remove all expressions that refer to register REGNO, since they are already invalid, and we are about to mark that register valid again and don't want the old expressions to reappear as valid.

References table_elt::exp, HASH_SIZE, i, table_elt::next_same_hash, refers_to_regno_p(), REG_P, remove_from_table(), and table.

Referenced by cse_insn(), and mention_regs().

◆ remove_invalid_subreg_refs()

static void remove_invalid_subreg_refs ( unsigned int regno,
poly_uint64 offset,
machine_mode mode )
static
Likewise for a subreg with subreg_reg REGNO, subreg_byte OFFSET, and mode MODE.

References exp(), table_elt::exp, GET_CODE, GET_MODE, GET_MODE_SIZE(), HASH_SIZE, i, table_elt::mode, table_elt::next_same_hash, refers_to_regno_p(), REG_P, REGNO, remove_from_table(), SUBREG_BYTE, SUBREG_REG, and table.

Referenced by mention_regs().

◆ remove_pseudo_from_table() [1/2]

static void remove_pseudo_from_table ( rtx x,
unsigned int hash )
static
Same as above, but X is a pseudo-register.

References lookup_for_remove(), and remove_from_table().

◆ remove_pseudo_from_table() [2/2]

static void remove_pseudo_from_table ( rtx ,
unsigned  )
static

◆ replace_dead_reg()

static rtx replace_dead_reg ( rtx x,
const_rtx old_rtx,
void * data )
static
Replace a dead pseudo in a DEBUG_INSN with replacement DEBUG_EXPR. Callback for simplify_replace_fn_rtx.

References GET_MODE, lowpart_subreg(), NULL_RTX, REG_P, REGNO, and replacements.

Referenced by delete_trivially_dead_insns().

◆ rest_of_handle_cse()

static unsigned int rest_of_handle_cse ( void )
static
Perform common subexpression elimination. Nonzero value from `cse_main' means that jumps were simplified and some code may now be unreachable, so do jump optimization again.

References cleanup_cfg(), CLEANUP_CFG_CHANGED, cse_cfg_altered, cse_main(), cse_not_expected, dump_file, dump_flags, dump_flow_info(), get_insns(), max_reg_num(), rebuild_jump_labels(), timevar_pop(), and timevar_push().

◆ rest_of_handle_cse2()

◆ rest_of_handle_cse_after_global_opts()

static unsigned int rest_of_handle_cse_after_global_opts ( void )
static

◆ SAFE_HASH()

static unsigned SAFE_HASH ( rtx x,
machine_mode mode )
inlinestatic

◆ safe_hash()

static unsigned safe_hash ( rtx x,
machine_mode mode )
inlinestatic
Like canon_hash but with no side effects, i.e. do_not_record and hash_arg_in_memory are not changed.

References hash_rtx(), table_elt::mode, and NULL.

Referenced by SAFE_HASH().

◆ set_live_p()

static bool set_live_p ( rtx set,
int * counts )
static
Return true if set is live.

References is_dead_reg(), SET_DEST, set_noop_p(), SET_SRC, and side_effects_p().

Referenced by insn_live_p().

◆ try_back_substitute_reg()

static void try_back_substitute_reg ( rtx set,
rtx_insn * insn )
static
Special handling for (set REG0 REG1) where REG0 is the "cheapest", cheaper than REG1. After cse, REG1 will probably not be used in the sequel, so (if easily done) change this insn to (set REG1 REG0) and replace REG1 with REG0 in the previous insn that computed their value. Then REG1 will become a dead store and won't cloud the situation for later optimizations. Do not make this change if REG1 is a hard register, because it will then be used in the sequel and we may be changing a two-operand insn into a three-operand insn. This is the last transformation that cse_insn will try to do.

References apply_change_group(), BB_HEAD, BLOCK_FOR_INSN(), DEBUG_INSN_P, find_reg_note(), qty_table_elem::first_reg, gcc_assert, GET_CODE, HARD_REGISTER_P, NONJUMP_INSN_P, NOTE_P, NULL_RTX, PATTERN(), PREV_INSN(), qty_table, reg_mentioned_p(), REG_P, REG_QTY, REGNO, REGNO_QTY_VALID_P, remove_note(), rtx_equal_p(), SET, SET_DEST, SET_SRC, set_unique_reg_note(), validate_change(), and XEXP.

Referenced by cse_insn().

◆ try_const_anchors()

static rtx try_const_anchors ( rtx src_const,
machine_mode mode )
static
Try to express the constant SRC_CONST using a register+offset expression derived from a constant anchor. Return it if successful or NULL_RTX, otherwise.

References compute_const_anchors(), find_reg_offset_for_const(), GEN_INT, HASH(), lookup(), table_elt::mode, NULL_RTX, and SCALAR_INT_MODE_P.

Referenced by cse_insn().

◆ use_related_value()

static rtx use_related_value ( rtx x,
struct table_elt * elt )
static
Given an expression X of type CONST, and ELT which is its table entry (or 0 if it is not in the hash table), return an alternate expression for X as a register plus integer. If none can be found, return 0.

References table_elt::exp, table_elt::first_same_value, GET_CODE, get_integer_term(), GET_MODE, get_related_value(), lookup(), table_elt::mode, table_elt::next_same_value, plus_constant(), REG_P, table_elt::related_value, rtx_equal_p(), and SAFE_HASH().

Referenced by cse_insn().

◆ validate_canon_reg()

static void validate_canon_reg ( rtx * xloc,
rtx_insn * insn )
static
Subroutine of canon_reg. Pass *XLOC through canon_reg, and validate the result if necessary. INSN is as for canon_reg.

References canon_reg(), gcc_assert, and validate_change().

Referenced by canon_reg().

Variable Documentation

◆ cse_cfg_altered

◆ cse_ebb_live_in

bitmap cse_ebb_live_in
static
Pointers to the live in/live out bitmaps for the boundaries of the current EBB.

Referenced by cse_extended_basic_block(), and make_regs_eqv().

◆ cse_ebb_live_out

bitmap cse_ebb_live_out
static

◆ cse_jumps_altered

bool cse_jumps_altered
static
True if CSE has altered conditional jump insns in such a way that jump optimization should be redone.

Referenced by cse_insn(), and cse_main().

◆ cse_reg_info_table

struct cse_reg_info* cse_reg_info_table
static
A table of cse_reg_info indexed by register numbers.

Referenced by get_cse_reg_info(), get_cse_reg_info_1(), and init_cse_reg_info().

◆ cse_reg_info_table_first_uninitialized

unsigned int cse_reg_info_table_first_uninitialized
static
The index of the first entry that has not been initialized.

Referenced by init_cse_reg_info().

◆ cse_reg_info_table_size

unsigned int cse_reg_info_table_size
static
The size of the above table.

Referenced by init_cse_reg_info().

◆ cse_reg_info_timestamp

unsigned int cse_reg_info_timestamp
static
The timestamp at the beginning of the current run of cse_extended_basic_block. We increment this variable at the beginning of the current run of cse_extended_basic_block. The timestamp field of a cse_reg_info entry matches the value of this variable if and only if the entry has been initialized during the current run of cse_extended_basic_block.

Referenced by get_cse_reg_info(), get_cse_reg_info_1(), init_cse_reg_info(), and new_basic_block().

◆ cse_rtl_hooks

const struct rtl_hooks cse_rtl_hooks = RTL_HOOKS_INITIALIZER
static

Referenced by cse_main().

◆ cse_visited_basic_blocks

sbitmap cse_visited_basic_blocks
static
A simple bitmap to track which basic blocks have been visited already as part of an already processed extended basic block.

Referenced by cse_extended_basic_block(), cse_find_path(), and cse_main().

◆ do_not_record

int do_not_record
static
canon_hash stores 1 in do_not_record if it notices a reference to PC or some other volatile subexpression.

Referenced by canon_hash(), cse_insn(), invariant_group_base_hasher::hash(), record_jump_cond(), and temp_slot_address_compute_hash().

◆ free_element_chain

struct table_elt* free_element_chain
static
Chain of `struct table_elt's made so far for this function but currently removed from the table.

Referenced by insert_with_costs(), new_basic_block(), and remove_from_table().

◆ hard_regs_in_table

HARD_REG_SET hard_regs_in_table
static
A HARD_REG_SET containing all the hard registers for which there is currently a REG expression in the hash table. Note the difference from the above variables, which indicate if the REG is mentioned in some expression in the table.

Referenced by insert_with_costs(), invalidate_for_call(), invalidate_reg(), and new_basic_block().

◆ hash_arg_in_memory

int hash_arg_in_memory
static
canon_hash stores 1 in hash_arg_in_memory if it notices a reference to memory within the expression being hashed.

Referenced by canon_hash(), cse_insn(), merge_equiv_classes(), and record_jump_cond().

◆ max_qty

int max_qty
static
Common subexpression elimination for GNU compiler. Copyright (C) 1987-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/>.
The basic idea of common subexpression elimination is to go through the code, keeping a record of expressions that would have the same value at the current scan point, and replacing expressions encountered with the cheapest equivalent expression. It is too complicated to keep track of the different possibilities when control paths merge in this code; so, at each label, we forget all that is known and start fresh. This can be described as processing each extended basic block separately. We have a separate pass to perform global CSE. Note CSE can turn a conditional or computed jump into a nop or an unconditional jump. When this occurs we arrange to run the jump optimizer after CSE to delete the unreachable code. We use two data structures to record the equivalent expressions: a hash table for most expressions, and a vector of "quantity numbers" to record equivalent (pseudo) registers. The use of the special data structure for registers is desirable because it is faster. It is possible because registers references contain a fairly small number, the register number, taken from a contiguously allocated series, and two register references are identical if they have the same number. General expressions do not have any such thing, so the only way to retrieve the information recorded on an expression other than a register is to keep it in a hash table. Registers and "quantity numbers": At the start of each basic block, all of the (hardware and pseudo) registers used in the function are given distinct quantity numbers to indicate their contents. During scan, when the code copies one register into another, we copy the quantity number. When a register is loaded in any other way, we allocate a new quantity number to describe the value generated by this operation. `REG_QTY (N)' records what quantity register N is currently thought of as containing. All real quantity numbers are greater than or equal to zero. If register N has not been assigned a quantity, `REG_QTY (N)' will equal -N - 1, which is always negative. Quantity numbers below zero do not exist and none of the `qty_table' entries should be referenced with a negative index. We also maintain a bidirectional chain of registers for each quantity number. The `qty_table` members `first_reg' and `last_reg', and `reg_eqv_table' members `next' and `prev' hold these chains. The first register in a chain is the one whose lifespan is least local. Among equals, it is the one that was seen first. We replace any equivalent register with that one. If two registers have the same quantity number, it must be true that REG expressions with qty_table `mode' must be in the hash table for both registers and must be in the same class. The converse is not true. Since hard registers may be referenced in any mode, two REG expressions might be equivalent in the hash table but not have the same quantity number if the quantity number of one of the registers is not the same mode as those expressions. Constants and quantity numbers When a quantity has a known constant value, that value is stored in the appropriate qty_table `const_rtx'. This is in addition to putting the constant in the hash table as is usual for non-regs. Whether a reg or a constant is preferred is determined by the configuration macro CONST_COSTS and will often depend on the constant value. In any event, expressions containing constants can be simplified, by fold_rtx. When a quantity has a known nearly constant value (such as an address of a stack slot), that value is stored in the appropriate qty_table `const_rtx'. Integer constants don't have a machine mode. However, cse determines the intended machine mode from the destination of the instruction that moves the constant. The machine mode is recorded in the hash table along with the actual RTL constant expression so that different modes are kept separate. Other expressions: To record known equivalences among expressions in general we use a hash table called `table'. It has a fixed number of buckets that contain chains of `struct table_elt' elements for expressions. These chains connect the elements whose expressions have the same hash codes. Other chains through the same elements connect the elements which currently have equivalent values. Register references in an expression are canonicalized before hashing the expression. This is done using `reg_qty' and qty_table `first_reg'. The hash code of a register reference is computed using the quantity number, not the register number. When the value of an expression changes, it is necessary to remove from the hash table not just that expression but all expressions whose values could be different as a result. 1. If the value changing is in memory, except in special cases ANYTHING referring to memory could be changed. That is because nobody knows where a pointer does not point. The function `invalidate_memory' removes what is necessary. The special cases are when the address is constant or is a constant plus a fixed register such as the frame pointer or a static chain pointer. When such addresses are stored in, we can tell exactly which other such addresses must be invalidated due to overlap. `invalidate' does this. All expressions that refer to non-constant memory addresses are also invalidated. `invalidate_memory' does this. 2. If the value changing is a register, all expressions containing references to that register, and only those, must be removed. Because searching the entire hash table for expressions that contain a register is very slow, we try to figure out when it isn't necessary. Precisely, this is necessary only when expressions have been entered in the hash table using this register, and then the value has changed, and then another expression wants to be added to refer to the register's new value. This sequence of circumstances is rare within any one basic block. `REG_TICK' and `REG_IN_TABLE', accessors for members of cse_reg_info, are used to detect this case. REG_TICK (i) is incremented whenever a value is stored in register i. REG_IN_TABLE (i) holds -1 if no references to register i have been entered in the table; otherwise, it contains the value REG_TICK (i) had when the references were entered. If we want to enter a reference and REG_IN_TABLE (i) != REG_TICK (i), we must scan and remove old references. Until we want to enter a new entry, the mere fact that the two vectors don't match makes the entries be ignored if anyone tries to match them. Registers themselves are entered in the hash table as well as in the equivalent-register chains. However, `REG_TICK' and `REG_IN_TABLE' do not apply to expressions which are simple register references. These expressions are removed from the table immediately when they become invalid, and this can be done even if we do not immediately search for all the expressions that refer to the register. A CLOBBER rtx in an instruction invalidates its operand for further reuse. A CLOBBER or SET rtx whose operand is a MEM:BLK invalidates everything that resides in memory. Related expressions: Constant expressions that differ only by an additive integer are called related. When a constant expression is put in the table, the related expression with no constant term is also entered. These are made to point at each other so that it is possible to find out if there exists any register equivalent to an expression related to a given expression.
Length of qty_table vector. We know in advance we will not need a quantity number this big.

Referenced by cse_extended_basic_block(), cse_main(), and make_new_qty().

◆ next_qty

int next_qty
static
Next quantity number to be allocated. This is 1 + the largest number needed so far.

Referenced by cse_extended_basic_block(), make_new_qty(), and new_basic_block().

◆ optimize_this_for_speed_p

bool optimize_this_for_speed_p
static

◆ qty_table

◆ recorded_label_ref

bool recorded_label_ref
static
True if we put a LABEL_REF into the hash table for an INSN without a REG_LABEL_OPERAND, we have to rerun jump after CSE to put in the note.

Referenced by cse_extended_basic_block(), and cse_main().

◆ reg_eqv_table

struct reg_eqv_elem* reg_eqv_table
static
The table of all register equivalence chains.

Referenced by cse_main(), delete_reg_equiv(), make_new_qty(), and make_regs_eqv().

◆ table

struct table_elt* table[HASH_SIZE]
static

Referenced by ipa_fn_summary::account_size_time(), add_mapping(), alloc_hash_table(), alloc_hash_table(), alloc_node(), allocate_vn_table(), avail_exprs_stack::avail_exprs_stack(), compute_hash_table(), compute_hash_table(), compute_hash_table_work(), compute_hash_table_work(), compute_local_properties(), compute_local_properties(), hash_table< decl_table_entry_hasher >::create_ggc(), create_trace_edges(), debug_tree(), decode_reg_name_and_count(), delete_insn(), delete_related_insns(), dump_hash_table(), dump_hash_table(), dwarf2out_end_source_file(), dwarf2out_set_ignored_loc(), dwarf2out_start_source_file(), emit_jump_table_data(), equiv_class_lookup_or_add(), final_scan_insn_1(), find_AT_string_in_table(), find_attr_url_entry(), find_bb_boundaries(), find_replaceable_exprs(), flush_hash_table(), force_nonfallthru_and_redirect(), free_hash_table(), free_hash_table(), free_vn_table(), get_initial_register_offset(), get_last_bb_insn(), gt_cleare_cache(), gt_ggc_mx(), handle_ignored_attributes_option(), hash_scan_call(), hash_scan_clobber(), hash_scan_insn(), hash_scan_insn(), hash_scan_set(), hash_scan_set(), hash_table< decl_table_entry_hasher >::hashtab_entry_note_pointers, include_pubname_in_output(), init_one_dwarf_reg_size(), insert_expr_in_table(), insert_set_in_table(), insert_with_costs(), instrument_decisions(), invalidate(), invalidate_for_call(), invalidate_memory(), invalidate_reg(), ipa_edge_args_sum_t::ipa_edge_args_sum_t(), ipa_edge_modification_sum::ipa_edge_modification_sum(), ipa_node_params_t::ipa_node_params_t(), ipa_profile_call_summaries::ipa_profile_call_summaries(), ipa_return_value_sum_t::ipa_return_value_sum_t(), ipa_sra_call_summaries::ipa_sra_call_summaries(), ipa_sra_function_summaries::ipa_sra_function_summaries(), ipcp_transformation_t::ipcp_transformation_t(), label_is_jump_target_p(), lookup(), lookup_for_remove(), lookup_page_table_entry(), lookup_set(), lto_input_mode_table(), make_edges(), maybe_reset_location_view(), merge_blocks_move_successor_nojumps(), new_basic_block(), output_line_info(), output_one_line_info_table(), patch_jump_insn(), print_node(), prune_hardreg_uses(), purge_dead_tablejump_edges(), md_reader::read_mapping(), rehash_using_reg(), remove_from_table(), remove_invalid_refs(), remove_invalid_subreg_refs(), rtl_tidy_fallthru_edge(), safe_lookup_page_table_entry(), set_eh_throw_stmt_table(), set_page_table_entry(), shorten_branches(), tablejump_p(), try_redirect_by_replacing_jump(), and vn_nary_op_insert_into().

◆ this_insn