GCC Middle and Back End API 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_elt * | lookup (rtx, unsigned, enum machine_mode) |
static struct table_elt * | lookup_for_remove (rtx, unsigned, enum machine_mode) |
static rtx | lookup_as_function (rtx, enum rtx_code) |
static struct table_elt * | insert_with_costs (rtx, struct table_elt *, unsigned, enum machine_mode, int, int) |
static struct table_elt * | insert (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_info * | get_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_info * | get_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_elt * | lookup () |
static struct table_elt * | lookup_for_remove () |
static rtx | lookup_as_function () |
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) |
static struct table_elt * | insert (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_pass * | make_pass_cse () |
static bool | gate_handle_cse2 () |
static unsigned int | rest_of_handle_cse2 () |
rtl_opt_pass * | make_pass_cse2 () |
static bool | gate_handle_cse_after_global_opts () |
static unsigned int | rest_of_handle_cse_after_global_opts () |
rtl_opt_pass * | make_pass_cse_after_global_opts () |
|
static |
Referenced by cse_insn(), and insert().
|
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 |
Referenced by approx_reg_cost().
|
static |
Subroutine of approx_reg_cost; called through for_each_rtx.
References targetm.
|
inlinestatic |
|
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().
Referenced by canonicalize_insn(), cse_insn(), cse_process_notes_1(), fold_rtx(), and validate_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 |
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 |
Referenced by invalidate().
|
static |
|
static |
Referenced by cse_extended_basic_block().
|
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 |
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 |
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 |
Count the number of stores into pseudo. Callback for note_stores.
Referenced by delete_trivially_dead_insns().
|
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 |
Referenced by cse_change_cc_mode_insn().
|
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().
Referenced by cse_change_cc_mode_insns(), and cse_condition_code_reg().
|
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.
Referenced by cse_cc_succs(), and cse_condition_code_reg().
|
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 |
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 |
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 |
Referenced by cse_main().
|
static |
Process a single extended basic block described by EBB_DATA.
References any_condjump_p(), branch_path::bb, bb_has_eh_pred(), bitmap_clear_bit(), function::can_throw_non_call_exceptions, cc0_rtx, cfun, changed, check_for_label_ref(), cse_cfg_altered, cse_ebb_live_in, cse_ebb_live_out, cse_insn(), cse_process_notes(), cse_visited_basic_blocks, delete_insn(), df_get_artificial_defs(), df_get_live_in(), df_get_live_out(), df_notes_rescan(), DF_REF_AT_TOP, find_edge(), flush_hash_table(), for_each_rtx(), free(), have_eh_succ_edges(), basic_block_def::index, invalidate(), max_qty, new_basic_block(), next_qty, optimize_bb_for_speed_p(), optimize_this_for_speed_p, cse_basic_block_data::path, cse_basic_block_data::path_size, prev_insn_cc0, prev_insn_cc0_mode, prev_nonnote_nondebug_insn(), purge_dead_edges(), qty_table, record_jump_equiv(), recorded_label_ref, reg_mentioned_p(), and this_insn_cc0.
|
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 |
Referenced by cse_extended_basic_block().
|
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 |
Perform cse on the instructions of a function. F is the first instruction. NREGS is one plus the highest pseudo-reg number used in the instruction. Return 2 if jump optimizations should be redone due to simplifications in conditional jump instructions. Return 1 if the CFG should be cleaned up because it has been modified. Return 0 otherwise.
References bitmap_bit_p(), bitmap_clear(), constant_pool_entries_cost, constant_pool_entries_regcost, cse_cfg_altered, cse_dump_path(), cse_extended_basic_block(), cse_find_path(), cse_jumps_altered, cse_prescan_path(), cse_rtl_hooks, cse_visited_basic_blocks, df_analyze(), DF_DEFER_INSN_RESCAN, DF_LR_RUN_DCE, df_note_add_problem(), df_set_flags(), dump_file, end_alias_analysis(), free(), general_rtl_hooks, get_insns(), init_alias_analysis(), init_cse_reg_info(), init_recog(), max_qty, max_reg_num(), cse_basic_block_data::nsets, cse_basic_block_data::path, cse_basic_block_data::path_size, pre_and_rev_post_order_compute(), recorded_label_ref, reg_eqv_table, reg_scan(), sbitmap_alloc(), and sbitmap_free().
Referenced by rest_of_handle_cse(), rest_of_handle_cse2(), and rest_of_handle_cse_after_global_opts().
|
static |
Referenced by cse_main().
|
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.
Referenced by cse_extended_basic_block(), and cse_process_notes_1().
|
static |
References 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 |
Referenced by invalidate(), invalidate_for_call(), and merge_equiv_classes().
|
static |
Remove REG from its equivalence class.
References qty_table_elem::first_reg, qty_table_elem::last_reg, reg_eqv_elem::next, reg_eqv_elem::prev, qty_table, and reg_eqv_table.
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().
Referenced by equiv_constant(), fold_rtx(), and record_jump_cond().
|
static |
Return a constant value currently equivalent to X. Return 0 if we don't know one.
References avoid_constant_pool_reference(), qty_table_elem::const_rtx, equiv_constant(), table_elt::exp, table_elt::first_same_value, gen_rtx_SUBREG(), lookup(), lookup_as_function(), table_elt::next_same_value, qty_table, simplify_subreg(), subreg_lowpart_offset(), and word_mode.
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 |
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 |
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 |
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 |
Referenced by fixed_base_plus_p(), and insert_with_costs().
|
static |
Nonzero if X has the form (PLUS frame-pointer integer).
References fixed_base_plus_p().
|
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().
Referenced by canonicalize_insn(), cse_insn(), find_comparison_args(), fold_rtx(), and record_jump_equiv().
|
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 |
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 |
|
static |
References flag_rerun_cse_after_global_opts.
|
staticread |
|
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 |
Referenced by get_cse_reg_info().
|
static |
Given REGNO, initialize the cse_reg_info entry for REGNO.
References cse_reg_info_table, cse_reg_info_timestamp, cse_reg_info::reg_in_table, cse_reg_info::reg_qty, cse_reg_info::reg_tick, cse_reg_info::subreg_ticked, and cse_reg_info::timestamp.
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().
|
inlinestatic |
Referenced by hash_rtx_cb().
|
inlinestatic |
Hash a string. Just add its bytes up.
|
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 |
Initialize CSE_REG_INFO_TABLE.
References cse_reg_info_table, cse_reg_info_table_first_uninitialized, cse_reg_info_table_size, cse_reg_info_timestamp, and free().
Referenced by cse_main().
|
staticread |
Wrap insert_with_costs by passing the default costs.
References approx_reg_cost(), and insert_with_costs().
|
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 |
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().
Referenced by cse_insn(), insert_regs(), mention_regs(), merge_equiv_classes(), and record_jump_cond().
|
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.
|
staticread |
Referenced by insert(), and insert_const_anchor().
|
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 |
Referenced by delete_trivially_dead_insns().
|
static |
Return true if insn is live.
References function::can_delete_dead_exceptions, cfun, insn_nothrow_p(), SET, and set_live_p().
|
static |
|
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 |
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 |
Referenced by cse_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 invalidate().
|
static |
Referenced by cse_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 invalidate(), and SET.
|
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 |
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().
|
inlinestatic |
Return true if X is a dead register.
Referenced by delete_trivially_dead_insns(), is_dead_debug_insn(), and set_live_p().
|
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.
Referenced by equiv_constant(), and fold_rtx().
|
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.
Referenced by remove_pseudo_from_table().
|
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 |
Referenced by insert_regs().
|
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 |
Referenced by insert_regs().
|
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, qty_table_elem::last_reg, reg_eqv_elem::next, reg_eqv_elem::prev, qty_table, and reg_eqv_table.
|
static |
Referenced by cse_insn(), insert_const_anchor(), insert_regs(), and 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().
Referenced by cse_insn(), and record_jump_cond().
|
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 |
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 |
|
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 |
Referenced by cse_insn().
|
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 |
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 |
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 |
Referenced by cse_extended_basic_block().
|
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 |
Referenced by cse_insn(), mention_regs(), merge_equiv_classes(), and record_jump_cond().
|
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 |
|
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 |
Referenced by cse_insn(), and mention_regs().
|
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 |
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 |
Referenced by invalidate(), and merge_equiv_classes().
|
static |
Same as above, but X is a pseudo-register.
References lookup_for_remove(), and remove_from_table().
|
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 |
|
static |
Run second CSE pass after loop optimizations.
References cleanup_cfg(), cse_condition_code_reg(), cse_main(), cse_not_expected, delete_trivially_dead_insns(), dump_file, dump_flags, dump_flow_info(), get_insns(), max_reg_num(), rebuild_jump_labels(), timevar_pop(), and timevar_push().
|
static |
Run second CSE pass after loop optimizations.
References cleanup_cfg(), cse_main(), cse_not_expected, delete_trivially_dead_insns(), get_insns(), max_reg_num(), purge_all_dead_edges(), rebuild_jump_labels(), timevar_pop(), and timevar_push().
|
inlinestatic |
|
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().
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 |
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 |
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().
Referenced by cse_insn().
|
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 |
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().
|
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().
|
static |
Referenced by cse_insn(), and cse_main().
|
static |
True if CSE has altered the CFG.
Referenced by cse_extended_basic_block(), and cse_main().
|
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().
|
static |
Referenced by cse_extended_basic_block(), and make_regs_eqv().
|
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().
|
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().
|
static |
The index of the first entry that has not been initialized.
Referenced by init_cse_reg_info().
|
static |
The size of the above table.
Referenced by init_cse_reg_info().
|
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().
|
static |
Referenced by cse_main().
|
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().
|
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().
|
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().
|
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().
|
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().
|
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().
|
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().
|
static |
Referenced by cse_extended_basic_block(), and notreg_cost().
|
static |
Referenced by cse_extended_basic_block(), fold_rtx(), and new_basic_block().
|
static |
Referenced by cse_extended_basic_block(), and fold_rtx().
|
static |
The table of all qtys, indexed by qty number.
Referenced by canon_reg(), cse_extended_basic_block(), cse_insn(), cse_process_notes_1(), delete_reg_equiv(), equiv_constant(), fold_rtx(), insert_regs(), insert_with_costs(), make_new_qty(), make_regs_eqv(), record_jump_cond(), and try_back_substitute_reg().
|
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().
|
static |
The table of all register equivalence chains.
Referenced by cse_main(), delete_reg_equiv(), make_new_qty(), and make_regs_eqv().
|
static |
Referenced by decode_reg_name_and_count(), dwarf2out_source_line(), emit_jump_table_data(), find_bb_boundaries(), find_replaceable_exprs(), first_htab_element(), flush_hash_table(), ggc_allocated_p(), insert_with_costs(), invalidate(), invalidate_for_call(), invalidate_memory(), lookup(), lookup_for_remove(), lookup_page_table_entry(), merge_blocks_move_successor_nojumps(), new_basic_block(), new_line_info_table(), output_line_info(), rehash_using_reg(), remove_from_table(), remove_invalid_refs(), remove_invalid_subreg_refs(), set_cur_line_info_table(), set_eh_throw_stmt_table(), set_page_table_entry(), tablejump_p(), and try_redirect_by_replacing_jump().
|
static |
Insn being scanned.
Referenced by cse_insn(), insert_with_costs(), replace_read(), and schedule_reg_move().
|
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().