GCC Middle and Back End API Reference
cse.c File Reference

Data Structures

struct  qty_table_elem
struct  change_cc_mode_args
struct  reg_eqv_elem
struct  cse_reg_info
struct  table_elt
struct  branch_path
struct  cse_basic_block_data
struct  check_dependence_data
struct  set
struct  dead_debug_insn_data

Functions

static bool fixed_base_plus_p (rtx x)
static int notreg_cost (rtx, enum rtx_code, int)
static int approx_reg_cost_1 (rtx *, void *)
static int approx_reg_cost (rtx)
static int preferable (int, int, int, int)
static void new_basic_block (void)
static void make_new_qty (unsigned int, enum machine_mode)
static void make_regs_eqv (unsigned int, unsigned int)
static void delete_reg_equiv (unsigned int)
static int mention_regs (rtx)
static int insert_regs (rtx, struct table_elt *, int)
static void remove_from_table (struct table_elt *, unsigned)
static void remove_pseudo_from_table (rtx, unsigned)
static struct table_eltlookup (rtx, unsigned, enum machine_mode)
static struct table_eltlookup_for_remove (rtx, unsigned, enum machine_mode)
static rtx lookup_as_function (rtx, enum rtx_code)
static struct table_eltinsert_with_costs (rtx, struct table_elt *, unsigned, enum machine_mode, int, int)
static struct table_eltinsert (rtx, struct table_elt *, unsigned, enum machine_mode)
static void merge_equiv_classes (struct table_elt *, struct table_elt *)
static void invalidate (rtx, enum machine_mode)
static void remove_invalid_refs (unsigned int)
static void remove_invalid_subreg_refs (unsigned int, unsigned int, enum machine_mode)
static void rehash_using_reg (rtx)
static void invalidate_memory (void)
static void invalidate_for_call (void)
static rtx use_related_value (rtx, struct table_elt *)
static unsigned canon_hash (rtx, enum machine_mode)
static unsigned safe_hash (rtx, enum machine_mode)
static unsigned hash_rtx_string (const char *)
static rtx canon_reg (rtx, rtx)
static enum rtx_code find_comparison_args (enum rtx_code, rtx *, rtx *, enum machine_mode *, enum machine_mode *)
static rtx fold_rtx (rtx, rtx)
static rtx equiv_constant (rtx)
static void record_jump_equiv (rtx, bool)
static void record_jump_cond (enum rtx_code, enum machine_mode, rtx, rtx, int)
static void cse_insn (rtx)
static void cse_prescan_path (struct cse_basic_block_data *)
static void invalidate_from_clobbers (rtx)
static void invalidate_from_sets_and_clobbers (rtx)
static rtx cse_process_notes (rtx, rtx, bool *)
static void cse_extended_basic_block (struct cse_basic_block_data *)
static int check_for_label_ref (rtx *, void *)
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 int check_dependence (rtx *, void *)
static void flush_hash_table (void)
static bool insn_live_p (rtx, int *)
static bool set_live_p (rtx, rtx, int *)
static int cse_change_cc_mode (rtx *, void *)
static void cse_change_cc_mode_insn (rtx, rtx)
static void cse_change_cc_mode_insns (rtx, rtx, rtx)
static enum machine_mode cse_cc_succs (basic_block, basic_block, rtx, rtx, bool)
static bool fixed_base_plus_p ()
DEBUG_FUNCTION void dump_class ()
static int approx_reg_cost_1 ()
static int approx_reg_cost ()
static int preferable ()
static int notreg_cost ()
static void init_cse_reg_info ()
static void get_cse_reg_info_1 ()
static struct cse_reg_infoget_cse_reg_info ()
static void make_new_qty ()
static void make_regs_eqv ()
static void delete_reg_equiv ()
static int mention_regs ()
static int insert_regs ()
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, enum machine_mode mode)
static void insert_const_anchors ()
static rtx find_reg_offset_for_const (struct table_elt *anchor_elt, HOST_WIDE_INT offs, unsigned *old)
static rtx try_const_anchors ()
static void remove_from_table ()
static void remove_pseudo_from_table ()
static struct table_eltlookup ()
static struct table_eltlookup_for_remove ()
static rtx lookup_as_function ()
static struct table_eltinsert_with_costs (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mode, int cost, int reg_cost)
static struct table_eltinsert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mode)
static void merge_equiv_classes ()
static int check_dependence ()
static void invalidate ()
static void remove_invalid_refs ()
static void rehash_using_reg ()
static rtx use_related_value ()
static unsigned hash_rtx_string ()
unsigned hash_rtx_cb (const_rtx x, enum machine_mode mode, int *do_not_record_p, int *hash_arg_in_memory_p, bool have_reg_qty, hash_rtx_callback_function cb)
unsigned hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p, int *hash_arg_in_memory_p, bool have_reg_qty)
static unsigned canon_hash ()
static unsigned safe_hash ()
int exp_equiv_p ()
static void validate_canon_reg ()
static rtx canon_reg ()
static rtx fold_rtx ()
static rtx equiv_constant ()
static void record_jump_equiv ()
static rtx record_jump_cond_subreg ()
static void try_back_substitute_reg ()
static int find_sets_in_insn ()
static void canonicalize_insn ()
static void cse_insn ()
static void invalidate_from_clobbers ()
static void invalidate_from_sets_and_clobbers ()
static rtx cse_process_notes_1 ()
static rtx cse_process_notes ()
static bool cse_find_path (basic_block first_bb, struct cse_basic_block_data *data, int follow_jumps)
static void cse_dump_path ()
static bool have_eh_succ_edges ()
static void cse_prescan_path ()
static void cse_extended_basic_block ()
static int cse_main ()
static int check_for_label_ref ()
static void count_reg_usage ()
static int is_dead_reg ()
static bool insn_live_p ()
static void count_stores ()
static int is_dead_debug_insn ()
static rtx replace_dead_reg ()
int delete_trivially_dead_insns ()
static int cse_change_cc_mode ()
static void cse_change_cc_mode_insn ()
static void cse_change_cc_mode_insns ()
static void cse_condition_code_reg ()
static bool gate_handle_cse ()
static unsigned int rest_of_handle_cse ()
rtl_opt_passmake_pass_cse ()
static bool gate_handle_cse2 ()
static unsigned int rest_of_handle_cse2 ()
rtl_opt_passmake_pass_cse2 ()
static bool gate_handle_cse_after_global_opts ()
static unsigned int rest_of_handle_cse_after_global_opts ()
rtl_opt_passmake_pass_cse_after_global_opts ()

Variables

static int max_qty
static int next_qty
static struct qty_table_elemqty_table
static rtx this_insn_cc0
static rtx prev_insn_cc0
static enum machine_mode
this_insn_cc0_mode 
prev_insn_cc0_mode
static rtx this_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 int constant_pool_entries_cost
static int constant_pool_entries_regcost
static bitmap cse_ebb_live_in
static bitmap cse_ebb_live_out
static sbitmap cse_visited_basic_blocks
static struct rtl_hooks cse_rtl_hooks = RTL_HOOKS_INITIALIZER

Function Documentation

static int approx_reg_cost ( rtx  )
static

Referenced by cse_insn(), and insert().

static int approx_reg_cost ( )
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 approx_reg_cost_1(), table_elt::cost, and for_each_rtx().

static int approx_reg_cost_1 ( rtx ,
void *   
)
static

Referenced by approx_reg_cost().

static int approx_reg_cost_1 ( )
static
Subroutine of approx_reg_cost; called through for_each_rtx.   

References targetm.

static unsigned canon_hash ( rtx  ,
enum  machine_mode 
)
inlinestatic
static unsigned canon_hash ( )
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, and hash_rtx().

static rtx canon_reg ( rtx  ,
rtx   
)
static
static rtx canon_reg ( )
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 first, qty_table_elem::first_reg, gen_rtx_REG(), qty_table, regno_reg_rtx, and validate_canon_reg().

static void canonicalize_insn ( )
static
Where possible, substitute every register reference in the N_SETS
   number of SETS in INSN with the 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(), canon_reg(), df_notes_rescan(), find_reg_note(), fold_rtx(), remove_note(), set::rtl, rtx_equal_p(), SET, set::src, and validate_change().

Referenced by cse_insn().

static int check_dependence ( rtx ,
void *   
)
static

Referenced by invalidate().

static int check_for_label_ref ( rtx ,
void *   
)
static
static int check_for_label_ref ( )
static
Called via for_each_rtx to see if an insn is using a LABEL_REF for
   which there isn't a REG_LABEL_OPERAND note.
   Return one if so.  DATA is the insn.   

References find_reg_note(), and label_is_jump_target_p().

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 HOST_WIDE_INT, and targetm.

Referenced by insert_const_anchors(), and try_const_anchors().

static void count_reg_usage ( )
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.   

References function::can_delete_dead_exceptions, cfun, find_reg_equal_equiv_note(), insn_nothrow_p(), pc_rtx, SET, and side_effects_p().

Referenced by delete_trivially_dead_insns().

static void count_stores ( )
static
Count the number of stores into pseudo.  Callback for note_stores.   

Referenced by delete_trivially_dead_insns().

static enum 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 cse_change_cc_mode_insns(), delete_insn(), delete_insn_and_edges(), edge_def::dest, edge_def::flags, gen_rtx_REG(), change_cc_mode_args::insn, modes, modified_in_p(), change_cc_mode_args::newreg, basic_block_def::preds, reg_set_p(), rtx_equal_p(), basic_block_def::succs, and targetm.

Referenced by cse_condition_code_reg().

static int cse_change_cc_mode ( rtx ,
void *   
)
static

Referenced by cse_change_cc_mode_insn().

static int cse_change_cc_mode ( )
static
This function is called via for_each_rtx.  The argument, NEWREG, is
   a condition code register with the desired mode.  If we are looking
   at the same register in a different mode, replace it with
   NEWREG.   

References change_cc_mode_args::insn, change_cc_mode_args::newreg, and validate_change().

static void cse_change_cc_mode_insn ( rtx  ,
rtx   
)
static
static void cse_change_cc_mode_insn ( )
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(), for_each_rtx(), change_cc_mode_args::insn, and change_cc_mode_args::newreg.

static void cse_change_cc_mode_insns ( rtx  ,
rtx  ,
rtx   
)
static
static void cse_change_cc_mode_insns ( )
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(), change_cc_mode_args::insn, and reg_set_p().

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

References cse_cc_succs(), cse_change_cc_mode_insn(), cse_change_cc_mode_insns(), gen_rtx_REG(), change_cc_mode_args::insn, modified_between_p(), change_cc_mode_args::newreg, reg_referenced_p(), reg_set_p(), and targetm.

Referenced by rest_of_handle_cse2().

static void cse_dump_path ( )
static
Dump the path in DATA to file F.  NSETS is the number of sets
   in the path.   

References branch_path::bb, dump_file, cse_basic_block_data::path, and cse_basic_block_data::path_size.

Referenced by cse_main().

static void cse_extended_basic_block ( struct cse_basic_block_data )
static

Referenced by cse_main().

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(), branch_path::bb, bitmap_bit_p(), bitmap_set_bit(), cfun, cse_visited_basic_blocks, edge_def::dest, find_edge(), edge_def::flags, function::has_nonlocal_label, basic_block_def::index, cse_basic_block_data::path, cse_basic_block_data::path_size, single_pred_p(), single_succ_edge(), single_succ_p(), and basic_block_def::succs.

Referenced by cse_main().

static void cse_insn ( rtx  )
static
static void cse_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 apply_change_group(), approx_reg_cost(), canon_reg(), canon_rtx(), canonicalize_insn(), cc0_rtx, condjump_p(), constant_pool_entries_cost, constant_pool_entries_regcost, copy_rtx(), table_elt::cost, cse_jumps_altered, delete_insn_and_edges(), set::dest_hash, df_notes_rescan(), do_not_record, emit_jump_insn_before(), table_elt::exp, exp_equiv_p(), find_reg_note(), find_sets_in_insn(), first, qty_table_elem::first_reg, table_elt::first_same_value, flush_hash_table(), fold_rtx(), force_const_mem(), gen_rtx_REG(), hash_arg_in_memory, HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT_M1U, set::inner_dest, insert(), insert_const_anchors(), insert_regs(), invalidate(), invalidate_for_call(), invalidate_from_clobbers(), invalidate_from_sets_and_clobbers(), invalidate_memory(), lookup(), memset(), mention_regs(), merge_equiv_classes(), new_mode(), table_elt::next_same_value, nonoverlapping_memrefs_p(), paradoxical_subreg_p(), pc_rtx, preferable(), table_elt::prev_same_value, qty_table, table_elt::regcost, regno_reg_rtx, rehash_using_reg(), remove_invalid_refs(), remove_note(), set::rtl, RTX_AUTOINC, rtx_equal_p(), SET, set_unique_reg_note(), shift, simplify_gen_subreg(), set::src, set::src_elt, set::src_hash, set::src_in_memory, set::src_volatile, targetm, this_insn, this_insn_cc0, trunc_int_for_mode(), try_back_substitute_reg(), try_const_anchors(), use_related_value(), validate_change(), validate_unshare_change(), and volatile_insn_p().

static int cse_main ( )
static
static void cse_prescan_path ( struct cse_basic_block_data )
static

Referenced by cse_main().

static void cse_prescan_path ( )
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 branch_path::bb, cse_basic_block_data::nsets, cse_basic_block_data::path, and cse_basic_block_data::path_size.

static rtx cse_process_notes ( rtx  ,
rtx  ,
bool *   
)
static
static rtx cse_process_notes ( )
static

References cse_process_notes_1().

static rtx cse_process_notes_1 ( )
static
Process X, part of the REG_NOTES of an insn.  Look at any REG_EQUAL notes
   and replace any registers in them with either an equivalent constant
   or the canonical form of the register.  If we are inside an address,
   only do this if the address remains valid.

   OBJECT is 0 except when within a MEM in which case it is the MEM.

   Return the replacement for X.   

References canon_reg(), qty_table_elem::const_rtx, copy_rtx(), cse_process_notes(), qty_table, and validate_change().

Referenced by cse_process_notes().

static void delete_reg_equiv ( unsigned  int)
static
static void delete_reg_equiv ( )
static
int delete_trivially_dead_insns ( )
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(), dead_debug_insn_data::counts, dbg_cnt(), delete_insn_and_edges(), df_insn_rescan(), dump_file, emit_debug_insn_before(), for_each_rtx(), free(), get_last_insn(), insn_live_p(), is_dead_debug_insn(), is_dead_reg(), make_debug_expr_from_rtl(), note_stores(), replace_dead_reg(), replacements, dead_debug_insn_data::replacements, dead_debug_insn_data::seen_repl, side_effects_p(), simplify_replace_fn_rtx(), timevar_pop(), timevar_push(), and VAR_INIT_STATUS_INITIALIZED.

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

void dump_class ( struct table_elt )
DEBUG_FUNCTION void dump_class ( )
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().

static rtx equiv_constant ( rtx  )
static
int exp_equiv_p ( )
Return 1 iff X and Y would canonicalize into the same thing,
   without actually constructing the canonicalization of either one.
   If VALIDATE is nonzero,
   we assume X is an expression being processed from the rtl
   and Y was found in the hash table.  We check register refs
   in Y for being marked as valid.

   If FOR_GCSE is true, we compare X and Y for equivalence for GCSE.   

Referenced by cse_insn(), expr_hasher::equal(), st_expr_hasher::equal(), expr_equiv_p(), find_comparison_args(), find_reg_offset_for_const(), fold_rtx(), lookup(), lookup_as_function(), lookup_for_remove(), merge_equiv_classes(), rehash_using_reg(), remove_reachable_equiv_notes(), replace_store_insn(), store_killed_in_insn(), store_killed_in_pat(), and temp_slot_address_eq().

static enum rtx_code find_comparison_args ( enum rtx_code  code,
rtx parg1,
rtx parg2,
enum machine_mode *  pmode1,
enum 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 (cc0) and *PARG2
   was (const_int 0), *PARG1 and *PARG2 will be set to the objects that were
   compared to produce cc0.

   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 table_elt::exp, exp_equiv_p(), table_elt::first_same_value, fold_rtx(), lookup(), table_elt::next_same_value, pointer_set_contains(), pointer_set_create(), pointer_set_destroy(), pointer_set_insert(), reversed_comparison_code(), rtx_addr_can_trap_p(), val_signbit_known_set_p(), and visited.

Referenced by fold_rtx(), and record_jump_equiv().

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 table_elt::exp, exp_equiv_p(), table_elt::first_same_value, table_elt::next_same_value, plus_constant(), and targetm.

Referenced by try_const_anchors().

static int find_sets_in_insn ( )
static
Record all the SETs in this instruction into SETS_PTR,
   and return the number of recorded sets.   

References pc_rtx, set::rtl, and SET.

Referenced by cse_insn().

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

References fixed_base_plus_p().

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

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

Referenced by cse_extended_basic_block(), and cse_insn().

static rtx fold_rtx ( rtx  ,
rtx   
)
static
static rtx fold_rtx ( )
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(), canon_reg(), canonicalize_change_group(), changed, qty_table_elem::comparison_const, comparison_dominates_p(), qty_table_elem::comparison_qty, const_true_rtx, copy_rtx(), table_elt::cost, equiv_constant(), exact_log2(), table_elt::exp, exp_equiv_p(), false_rtx, find_comparison_args(), table_elt::first_same_value, fold_rtx(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, lookup(), lookup_as_function(), table_elt::next_same_value, plus_constant(), prev_insn_cc0, prev_insn_cc0_mode, qty_table, reg_mentioned_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, side_effects_p(), simplify_binary_operation(), simplify_gen_binary(), simplify_relational_operation(), simplify_ternary_operation(), simplify_unary_operation(), true_rtx, validate_change(), and validate_unshare_change().

static bool gate_handle_cse ( )
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.   
static bool gate_handle_cse2 ( )
static
static bool gate_handle_cse_after_global_opts ( )
static
static struct cse_reg_info* get_cse_reg_info ( unsigned int  regno)
staticread
static struct cse_reg_info* get_cse_reg_info ( )
staticread
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.

static void get_cse_reg_info_1 ( unsigned int  regno)
static

Referenced by get_cse_reg_info().

static void get_cse_reg_info_1 ( )
static
unsigned hash_rtx ( const_rtx  x,
enum machine_mode  mode,
int *  do_not_record_p,
int *  hash_arg_in_memory_p,
bool  have_reg_qty 
)
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.   

References hash_rtx_cb().

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

unsigned hash_rtx_cb ( const_rtx  x,
enum machine_mode  mode,
int *  do_not_record_p,
int *  hash_arg_in_memory_p,
bool  have_reg_qty,
hash_rtx_callback_function  cb 
)
Same as hash_rtx, but call CB on each rtx if it is not NULL.
   When the callback returns true, we continue with the new rtx.   

References fixed_hash(), global_regs, hash_rtx_cb(), hash_rtx_string(), real_hash(), reload_completed, and targetm.

Referenced by hash_rtx(), and hash_rtx_cb().

static unsigned hash_rtx_string ( const char *  )
inlinestatic

Referenced by hash_rtx_cb().

static unsigned hash_rtx_string ( )
inlinestatic
Hash a string.  Just add its bytes up.   
static bool have_eh_succ_edges ( )
static
Return true if BB has exception handling successor edges.   

References edge_def::flags, and basic_block_def::succs.

Referenced by cse_extended_basic_block().

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

References approx_reg_cost(), and insert_with_costs().

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

References exp(), insert(), insert_with_costs(), lookup(), mention_regs(), and plus_constant().

Referenced by insert_const_anchors().

static void insert_const_anchors ( )
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(), HOST_WIDE_INT, and insert_const_anchor().

Referenced by cse_insn().

static int insert_regs ( rtx  ,
struct table_elt ,
int   
)
static
static int insert_regs ( )
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 nonzero, 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.

   Nonzero 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, insert_regs(), make_new_qty(), make_regs_eqv(), mention_regs(), table_elt::next_same_value, and qty_table.

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

Referenced by insert(), and insert_const_anchor().

static struct table_elt* insert_with_costs ( rtx  x,
struct table_elt classp,
unsigned int  hash,
enum machine_mode  mode,
int  cost,
int  reg_cost 
)
staticread
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, qty_table_elem::const_insn, qty_table_elem::const_rtx, table_elt::cost, table_elt::exp, table_elt::first_same_value, fixed_base_plus_p(), free_element_chain, get_related_value(), hard_regs_in_table, insert(), lookup(), table_elt::next_same_hash, table_elt::next_same_value, table_elt::prev_same_hash, table_elt::prev_same_value, qty_table, table_elt::regcost, table_elt::related_value, table, and this_insn.

static bool insn_live_p ( rtx  ,
int *   
)
static
static bool insn_live_p ( )
static
Return true if insn is live.   

References function::can_delete_dead_exceptions, cfun, insn_nothrow_p(), SET, and set_live_p().

static void invalidate ( )
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 check_dependence_data::addr, table_elt::canon_exp, canon_rtx(), check_dependence(), delete_reg_equiv(), table_elt::exp, check_dependence_data::exp, for_each_rtx(), get_addr(), hard_regs_in_table, HOST_WIDE_INT, invalidate(), check_dependence_data::mode, table_elt::next_same_hash, remove_from_table(), remove_pseudo_from_table(), and table.

static void invalidate_for_call ( )
static
Remove from the hash table any expression that is a call-clobbered
   register.  Also update their TICK values.   

References delete_reg_equiv(), table_elt::exp, hard_regs_in_table, table_elt::next_same_hash, remove_from_table(), and table.

Referenced by cse_insn().

static void invalidate_from_clobbers ( rtx  )
static

Referenced by cse_insn().

static void invalidate_from_clobbers ( )
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 invalidate().

static void invalidate_from_sets_and_clobbers ( rtx  )
static

Referenced by cse_insn().

static void invalidate_from_sets_and_clobbers ( )
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 invalidate(), and SET.

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

References table_elt::next_same_hash, remove_from_table(), and table.

Referenced by cse_insn().

static int is_dead_debug_insn ( )
static
Return if a DEBUG_INSN needs to be reset because some dead
   pseudo doesn't have a replacement.  Callback for for_each_rtx.   

References dead_debug_insn_data::counts, is_dead_reg(), dead_debug_insn_data::replacements, and dead_debug_insn_data::seen_repl.

Referenced by delete_trivially_dead_insns().

static int is_dead_reg ( )
inlinestatic
Return true if X is a dead register.   

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

static struct table_elt* lookup ( )
staticread
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::next_same_hash, and table.

static rtx lookup_as_function ( rtx  ,
enum  rtx_code 
)
static

Referenced by equiv_constant(), and fold_rtx().

static rtx lookup_as_function ( )
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, lookup(), and table_elt::next_same_value.

static struct table_elt* lookup_for_remove ( rtx  ,
unsigned  ,
enum  machine_mode 
)
staticread
static struct table_elt* lookup_for_remove ( )
staticread
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::next_same_hash, and table.

static void make_new_qty ( unsigned  int,
enum  machine_mode 
)
static

Referenced by insert_regs().

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

References qty_table_elem::const_insn, qty_table_elem::const_rtx, qty_table_elem::first_reg, qty_table_elem::last_reg, max_qty, reg_eqv_elem::next, next_qty, reg_eqv_elem::prev, qty_table, and reg_eqv_table.

rtl_opt_pass* make_pass_cse ( )
rtl_opt_pass* make_pass_cse2 ( )
rtl_opt_pass* make_pass_cse_after_global_opts ( )
static void make_regs_eqv ( unsigned  int,
unsigned  int 
)
static

Referenced by insert_regs().

static void make_regs_eqv ( )
static
static int mention_regs ( rtx  )
static
static int mention_regs ( )
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 1 if we have done something that may have changed the hash code
   of X.   

References changed, insert_regs(), mention_regs(), rehash_using_reg(), remove_invalid_refs(), and remove_invalid_subreg_refs().

static void merge_equiv_classes ( struct table_elt ,
struct table_elt  
)
static

Referenced by cse_insn(), and record_jump_cond().

static void merge_equiv_classes ( )
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 delete_reg_equiv(), exp(), table_elt::exp, exp_equiv_p(), table_elt::first_same_value, hash_arg_in_memory, insert(), insert_regs(), table_elt::next_same_value, rehash_using_reg(), remove_from_table(), and remove_pseudo_from_table().

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

References cse_reg_info_timestamp, first, free_element_chain, hard_regs_in_table, last, next_qty, table_elt::next_same_hash, prev_insn_cc0, and table.

Referenced by cse_extended_basic_block().

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

References optimize_this_for_speed_p, rtx_cost(), and subreg_lowpart_p().

static int preferable ( int  ,
int  ,
int  ,
int   
)
static

Referenced by cse_insn().

static int preferable ( )
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.   
static void record_jump_cond ( enum rtx_code  code,
enum machine_mode  mode,
rtx  op0,
rtx  op1,
int  reversed_nonequality 
)
static
We know that comparison CODE applied to OP0 and OP1 in MODE is true.
   REVERSED_NONEQUALITY is nonzero if CODE had to be swapped.
   Make any useful entries we can with that information.  Called from
   above function and called recursively.   

References qty_table_elem::comparison_const, qty_table_elem::comparison_qty, do_not_record, equiv_constant(), table_elt::first_same_value, hash_arg_in_memory, insert(), insert_regs(), lookup(), merge_equiv_classes(), paradoxical_subreg_p(), qty_table, record_jump_cond_subreg(), rehash_using_reg(), rtx_equal_p(), and subreg_lowpart_p().

Referenced by record_jump_equiv().

static rtx record_jump_cond_subreg ( )
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 lowpart_subreg().

Referenced by record_jump_cond().

static void record_jump_equiv ( rtx  ,
bool   
)
static
static void record_jump_equiv ( )
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(), pc_rtx, pc_set(), record_jump_cond(), and reversed_comparison_code_parts().

static void rehash_using_reg ( rtx  )
static
static void rehash_using_reg ( )
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(), table_elt::next_same_hash, table_elt::prev_same_hash, reg_mentioned_p(), and table.

static void remove_from_table ( )
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, 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.

static void remove_invalid_refs ( unsigned  int)
static

Referenced by cse_insn(), and mention_regs().

static void remove_invalid_refs ( )
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, table_elt::next_same_hash, refers_to_regno_p(), remove_from_table(), and table.

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

References exp(), table_elt::exp, table_elt::next_same_hash, offset, refers_to_regno_p(), remove_from_table(), and table.

Referenced by mention_regs().

static void remove_pseudo_from_table ( rtx  ,
unsigned   
)
static

Referenced by invalidate(), and merge_equiv_classes().

static void remove_pseudo_from_table ( )
static
Same as above, but X is a pseudo-register.   

References lookup_for_remove(), and remove_from_table().

static rtx replace_dead_reg ( )
static
Replace a dead pseudo in a DEBUG_INSN with replacement DEBUG_EXPR.
   Callback for simplify_replace_fn_rtx.   

References lowpart_subreg(), and replacements.

Referenced by delete_trivially_dead_insns().

static unsigned int rest_of_handle_cse2 ( )
static
static unsigned int rest_of_handle_cse_after_global_opts ( )
static
static unsigned safe_hash ( rtx  ,
enum  machine_mode 
)
inlinestatic
static unsigned safe_hash ( )
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().

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

References cc0_rtx, is_dead_reg(), next_nonnote_nondebug_insn(), reg_referenced_p(), set_noop_p(), and side_effects_p().

Referenced by insn_live_p().

static void try_back_substitute_reg ( )
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(), find_reg_note(), qty_table_elem::first_reg, qty_table, reg_mentioned_p(), remove_note(), rtx_equal_p(), SET, and validate_change().

Referenced by cse_insn().

static rtx try_const_anchors ( )
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(), HOST_WIDE_INT, and lookup().

Referenced by cse_insn().

static rtx use_related_value ( rtx  ,
struct table_elt  
)
static

Referenced by cse_insn().

static rtx use_related_value ( )
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_integer_term(), get_related_value(), HOST_WIDE_INT, lookup(), table_elt::next_same_value, offset, plus_constant(), table_elt::related_value, and rtx_equal_p().

static void validate_canon_reg ( )
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(), and validate_change().

Referenced by canon_reg().


Variable Documentation

int constant_pool_entries_cost
static
Set to the cost of a constant pool reference if one was found for a
   symbolic constant.  If this was found, it means we should try to
   convert constants into constant pool entries if they don't fit in
   the insn.   

Referenced by cse_insn(), and cse_main().

int constant_pool_entries_regcost
static

Referenced by cse_insn(), and cse_main().

bool cse_cfg_altered
static
True if CSE has altered the CFG.   

Referenced by cse_extended_basic_block(), and cse_main().

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().

bitmap cse_ebb_live_out
static
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().

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().

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().

unsigned int cse_reg_info_table_size
static
The size of the above table.   

Referenced by init_cse_reg_info().

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().

struct rtl_hooks cse_rtl_hooks = RTL_HOOKS_INITIALIZER
static

Referenced by cse_main().

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().

int do_not_record
static
canon_hash stores 1 in do_not_record
   if it notices a reference to CC0, 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().

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_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(), invalidate_for_call(), and new_basic_block().

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().

int max_qty
static
@verbatim Common subexpression elimination for GNU compiler.

Copyright (C) 1987-2013 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().

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().

bool optimize_this_for_speed_p
static
rtx prev_insn_cc0
static
enum machine_mode this_insn_cc0_mode prev_insn_cc0_mode
static
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().

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().

rtx this_insn
static
Insn being scanned.   

Referenced by cse_insn(), insert_with_costs(), replace_read(), and schedule_reg_move().

rtx this_insn_cc0
static
For machines that have a CC0, we do not record its value in the hash
   table since its use is guaranteed to be the insn immediately following
   its definition and any other insn is presumed to invalidate it.

   Instead, we store below the current and last value assigned to CC0.
   If it should happen to be a constant, it is stored in preference
   to the actual assigned value.  In case it is a constant, we store
   the mode in which the constant should be interpreted.   

Referenced by cse_extended_basic_block(), and cse_insn().