/* Number of cuids. */
static int max_cuid;
-/* Mapping of cuids to insns. */
-static rtx *cuid_insn;
-
-/* Get insn from cuid. */
-#define CUID_INSN(CUID) (cuid_insn[CUID])
-
/* Maximum register number in function prior to doing gcse + 1.
Registers created during this pass have regno >= max_gcse_regno.
This is named with "gcse" to not collide with global of same name. */
static void hash_scan_call (rtx, rtx, struct hash_table *);
static int want_to_gcse_p (rtx);
static bool can_assign_to_reg_p (rtx);
-static bool gcse_constant_p (rtx);
-static int oprs_unchanged_p (rtx, rtx, int);
-static int oprs_anticipatable_p (rtx, rtx);
-static int oprs_available_p (rtx, rtx);
+static bool gcse_constant_p (const_rtx);
+static int oprs_unchanged_p (const_rtx, const_rtx, int);
+static int oprs_anticipatable_p (const_rtx, const_rtx);
+static int oprs_available_p (const_rtx, const_rtx);
static void insert_expr_in_table (rtx, enum machine_mode, rtx, int, int,
struct hash_table *);
static void insert_set_in_table (rtx, rtx, struct hash_table *);
-static unsigned int hash_expr (rtx, enum machine_mode, int *, int);
+static unsigned int hash_expr (const_rtx, enum machine_mode, int *, int);
static unsigned int hash_set (int, int);
-static int expr_equiv_p (rtx, rtx);
+static int expr_equiv_p (const_rtx, const_rtx);
static void record_last_reg_set_info (rtx, int);
static void record_last_mem_set_info (rtx);
static void record_last_set_info (rtx, const_rtx, void *);
static struct expr *lookup_set (unsigned int, struct hash_table *);
static struct expr *next_set (unsigned int, struct expr *);
static void reset_opr_set_tables (void);
-static int oprs_not_set_p (rtx, rtx);
+static int oprs_not_set_p (const_rtx, const_rtx);
static void mark_call (rtx);
static void mark_set (rtx, rtx);
static void mark_clobber (rtx, rtx);
static void mark_oprs_set (rtx);
static void alloc_cprop_mem (int, int);
static void free_cprop_mem (void);
-static void compute_transp (rtx, int, sbitmap *, int);
+static void compute_transp (const_rtx, int, sbitmap *, int);
static void compute_transpout (void);
static void compute_local_properties (sbitmap *, sbitmap *, sbitmap *,
struct hash_table *);
static struct expr *find_avail_set (int, rtx);
static int cprop_jump (basic_block, rtx, rtx, rtx, rtx);
static void mems_conflict_for_gcse_p (rtx, const_rtx, void *);
-static int load_killed_in_block_p (basic_block, int, rtx, int);
+static int load_killed_in_block_p (const_basic_block, int, const_rtx, int);
static void canon_list_insert (rtx, const_rtx, void *);
static int cprop_insn (rtx, int);
static int cprop (int);
static int one_cprop_pass (int, bool, bool);
static bool constprop_register (rtx, rtx, rtx, bool);
static struct expr *find_bypass_set (int, int);
-static bool reg_killed_on_edge (rtx, edge);
+static bool reg_killed_on_edge (const_rtx, const_edge);
static int bypass_block (basic_block, rtx, rtx);
static int bypass_conditional_jumps (void);
static void alloc_pre_mem (int, int);
static int enumerate_ldsts (void);
static inline struct ls_expr * first_ls_expr (void);
static inline struct ls_expr * next_ls_expr (struct ls_expr *);
-static int simple_mem (rtx);
+static int simple_mem (const_rtx);
static void invalidate_any_buried_refs (rtx);
static void compute_ld_motion_mems (void);
static void trim_ld_motion_mems (void);
static void update_ld_motion_stores (struct expr *);
static void reg_set_info (rtx, const_rtx, void *);
static void reg_clear_last_set (rtx, const_rtx, void *);
-static bool store_ops_ok (rtx, int *);
+static bool store_ops_ok (const_rtx, int *);
static rtx extract_mentioned_regs (rtx);
static rtx extract_mentioned_regs_helper (rtx, rtx);
static void find_moveable_store (rtx, int *, int *);
static int compute_store_table (void);
-static bool load_kills_store (rtx, rtx, int);
-static bool find_loads (rtx, rtx, int);
-static bool store_killed_in_insn (rtx, rtx, rtx, int);
-static bool store_killed_after (rtx, rtx, rtx, basic_block, int *, rtx *);
-static bool store_killed_before (rtx, rtx, rtx, basic_block, int *);
+static bool load_kills_store (const_rtx, const_rtx, int);
+static bool find_loads (const_rtx, const_rtx, int);
+static bool store_killed_in_insn (const_rtx, const_rtx, const_rtx, int);
+static bool store_killed_after (const_rtx, const_rtx, const_rtx, const_basic_block, int *, rtx *);
+static bool store_killed_before (const_rtx, const_rtx, const_rtx, const_basic_block, int *);
static void build_store_vectors (void);
static void insert_insn_start_basic_block (rtx, basic_block);
static int insert_store (struct ls_expr *, edge);
uid_cuid[INSN_UID (insn)] = i;
}
- /* Create a table mapping cuids to insns. */
-
max_cuid = i;
- cuid_insn = gcalloc (max_cuid + 1, sizeof (rtx));
- i = 0;
- FOR_EACH_BB (bb)
- FOR_BB_INSNS (bb, insn)
- if (INSN_P (insn))
- CUID_INSN (i++) = insn;
/* Allocate vars to track sets of regs. */
reg_set_bitmap = BITMAP_ALLOC (NULL);
free_gcse_mem (void)
{
free (uid_cuid);
- free (cuid_insn);
BITMAP_FREE (reg_set_bitmap);
case SUBREG:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_FIXED:
case CONST_VECTOR:
case CALL:
return 0;
or from INSN to the end of INSN's basic block (if AVAIL_P != 0). */
static int
-oprs_unchanged_p (rtx x, rtx insn, int avail_p)
+oprs_unchanged_p (const_rtx x, const_rtx insn, int avail_p)
{
int i, j;
enum rtx_code code;
case CONST:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_FIXED:
case CONST_VECTOR:
case SYMBOL_REF:
case LABEL_REF:
load_killed_in_block_p. A memory reference for a load instruction,
mems_conflict_for_gcse_p will see if a memory store conflicts with
this memory load. */
-static rtx gcse_mem_operand;
+static const_rtx gcse_mem_operand;
/* DEST is the output of an instruction. If it is a memory reference, and
possibly conflicts with the load found in gcse_mem_operand, then set
AVAIL_P to 0. */
static int
-load_killed_in_block_p (basic_block bb, int uid_limit, rtx x, int avail_p)
+load_killed_in_block_p (const_basic_block bb, int uid_limit, const_rtx x, int avail_p)
{
rtx list_entry = modify_mem_list[bb->index];
the start of INSN's basic block up to but not including INSN. */
static int
-oprs_anticipatable_p (rtx x, rtx insn)
+oprs_anticipatable_p (const_rtx x, const_rtx insn)
{
return oprs_unchanged_p (x, insn, 0);
}
INSN to the end of INSN's basic block. */
static int
-oprs_available_p (rtx x, rtx insn)
+oprs_available_p (const_rtx x, const_rtx insn)
{
return oprs_unchanged_p (x, insn, 1);
}
the current size of the hash table to be probed. */
static unsigned int
-hash_expr (rtx x, enum machine_mode mode, int *do_not_record_p,
+hash_expr (const_rtx x, enum machine_mode mode, int *do_not_record_p,
int hash_table_size)
{
unsigned int hash;
/* Return nonzero if exp1 is equivalent to exp2. */
static int
-expr_equiv_p (rtx x, rtx y)
+expr_equiv_p (const_rtx x, const_rtx y)
{
return exp_equiv_p (x, y, 0, true);
}
the purposes of GCSE's constant propagation. */
static bool
-gcse_constant_p (rtx x)
+gcse_constant_p (const_rtx x)
{
/* Consider a COMPARE of two integers constant. */
if (GET_CODE (x) == COMPARE
modified. Here we want to search from INSN+1 on, but
oprs_available_p searches from INSN on. */
&& (insn == BB_END (BLOCK_FOR_INSN (insn))
- || ((tmp = next_nonnote_insn (insn)) != NULL_RTX
- && oprs_available_p (pat, tmp))))
+ || (tmp = next_nonnote_insn (insn)) == NULL_RTX
+ || BLOCK_FOR_INSN (tmp) != BLOCK_FOR_INSN (insn)
+ || oprs_available_p (pat, tmp)))
insert_set_in_table (pat, insn, table);
}
/* In case of store we want to consider the memory value as available in
INSN's basic block. */
static int
-oprs_not_set_p (rtx x, rtx insn)
+oprs_not_set_p (const_rtx x, const_rtx insn)
{
int i, j;
enum rtx_code code;
case CONST:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_FIXED:
case CONST_VECTOR:
case SYMBOL_REF:
case LABEL_REF:
bit in BMAP. */
static void
-compute_transp (rtx x, int indx, sbitmap *bmap, int set_p)
+compute_transp (const_rtx x, int indx, sbitmap *bmap, int set_p)
{
int i, j;
basic_block bb;
case CONST:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_FIXED:
case CONST_VECTOR:
case SYMBOL_REF:
case LABEL_REF:
with our replacement. */
if (note != 0 && REG_NOTE_KIND (note) == REG_EQUAL)
set_unique_reg_note (insn, REG_EQUAL,
- simplify_replace_rtx (XEXP (note, 0), from, to));
+ simplify_replace_rtx (XEXP (note, 0), from,
+ copy_rtx (to)));
if (!success && set && reg_mentioned_p (from, SET_SRC (set)))
{
/* If above failed and this is a single set, try to simplify the source of
}
purge_dead_edges (bb);
+ /* If a conditional jump has been changed into unconditional jump, remove
+ the jump and make the edge fallthru - this is always called in
+ cfglayout mode. */
+ if (new != pc_rtx && simplejump_p (jump))
+ {
+ edge e;
+ edge_iterator ei;
+
+ for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ei_next (&ei))
+ if (e->dest != EXIT_BLOCK_PTR
+ && BB_HEAD (e->dest) == JUMP_LABEL (jump))
+ {
+ e->flags |= EDGE_FALLTHRU;
+ break;
+ }
+ delete_insn (jump);
+ }
+
return 1;
}
it. COND is either an EQ or NE comparison. */
static bool
-implicit_set_cond_p (rtx cond)
+implicit_set_cond_p (const_rtx cond)
{
- enum machine_mode mode = GET_MODE (XEXP (cond, 0));
- rtx cst = XEXP (cond, 1);
+ const enum machine_mode mode = GET_MODE (XEXP (cond, 0));
+ const_rtx cst = XEXP (cond, 1);
/* We can't perform this optimization if either operand might be or might
contain a signed zero. */
valid prior to commit_edge_insertions. */
static bool
-reg_killed_on_edge (rtx reg, edge e)
+reg_killed_on_edge (const_rtx reg, const_edge e)
{
rtx insn;
return changed;
}
\f
-/* If X contains any LABEL_REF's, add REG_LABEL notes for them to INSN.
- If notes are added to an insn which references a CODE_LABEL, the
- LABEL_NUSES count is incremented. We have to add REG_LABEL notes,
- because the following loop optimization pass requires them. */
+/* If X contains any LABEL_REF's, add REG_LABEL_OPERAND notes for them
+ to INSN. If such notes are added to an insn which references a
+ CODE_LABEL, the LABEL_NUSES count is incremented. We have to add
+ that note, because the following loop optimization pass requires
+ them. */
/* ??? If there was a jump optimization pass after gcse and before loop,
then we would not need to do this here, because jump would add the
- necessary REG_LABEL notes. */
+ necessary REG_LABEL_OPERAND and REG_LABEL_TARGET notes. */
static void
add_label_notes (rtx x, rtx insn)
We no longer ignore such label references (see LABEL_REF handling in
mark_jump_label for additional information). */
- REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, XEXP (x, 0),
- REG_NOTES (insn));
+ /* There's no reason for current users to emit jump-insns with
+ such a LABEL_REF, so we don't have to handle REG_LABEL_TARGET
+ notes. */
+ gcc_assert (!JUMP_P (insn));
+ REG_NOTES (insn)
+ = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, XEXP (x, 0),
+ REG_NOTES (insn));
if (LABEL_P (XEXP (x, 0)))
LABEL_NUSES (XEXP (x, 0))++;
+
return;
}
the convergence. */
FOR_EACH_BB_REVERSE (bb)
{
- changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index], antloc[bb->index],
- hoist_vbeout[bb->index], transp[bb->index]);
if (bb->next_bb != EXIT_BLOCK_PTR)
- sbitmap_intersection_of_succs (hoist_vbeout[bb->index], hoist_vbein, bb->index);
+ sbitmap_intersection_of_succs (hoist_vbeout[bb->index],
+ hoist_vbein, bb->index);
+
+ changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index],
+ antloc[bb->index],
+ hoist_vbeout[bb->index],
+ transp[bb->index]);
}
passes++;
ld_motion list, otherwise we let the usual aliasing take care of it. */
static int
-simple_mem (rtx x)
+simple_mem (const_rtx x)
{
if (! MEM_P (x))
return 0;
due to set of registers in bitmap REGS_SET. */
static bool
-store_ops_ok (rtx x, int *regs_set)
+store_ops_ok (const_rtx x, int *regs_set)
{
- rtx reg;
+ const_rtx reg;
for (; x; x = XEXP (x, 1))
{
case CONST:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_FIXED:
case CONST_VECTOR:
case SYMBOL_REF:
case LABEL_REF:
after the X. */
static bool
-load_kills_store (rtx x, rtx store_pattern, int after)
+load_kills_store (const_rtx x, const_rtx store_pattern, int after)
{
if (after)
return anti_dependence (x, store_pattern);
after the insn X. */
static bool
-find_loads (rtx x, rtx store_pattern, int after)
+find_loads (const_rtx x, const_rtx store_pattern, int after)
{
const char * fmt;
int i, j;
}
static inline bool
-store_killed_in_pat (rtx x, rtx pat, int after)
+store_killed_in_pat (const_rtx x, const_rtx pat, int after)
{
if (GET_CODE (pat) == SET)
{
after the insn. Return true if it does. */
static bool
-store_killed_in_insn (rtx x, rtx x_regs, rtx insn, int after)
+store_killed_in_insn (const_rtx x, const_rtx x_regs, const_rtx insn, int after)
{
- rtx reg, base, note, pat;
+ const_rtx reg, base, note, pat;
if (!INSN_P (insn))
return false;
is killed, return the last insn in that it occurs in FAIL_INSN. */
static bool
-store_killed_after (rtx x, rtx x_regs, rtx insn, basic_block bb,
+store_killed_after (const_rtx x, const_rtx x_regs, const_rtx insn, const_basic_block bb,
int *regs_set_after, rtx *fail_insn)
{
rtx last = BB_END (bb), act;
within basic block BB. X_REGS is list of registers mentioned in X.
REGS_SET_BEFORE is bitmap of registers set before or in this insn. */
static bool
-store_killed_before (rtx x, rtx x_regs, rtx insn, basic_block bb,
+store_killed_before (const_rtx x, const_rtx x_regs, const_rtx insn, const_basic_block bb,
int *regs_set_before)
{
rtx first = BB_HEAD (bb);
/* If gcse or cse altered any jumps, rerun jump optimizations to clean
things up. */
- if (tem || tem2)
+ if (tem || tem2 == 2)
{
timevar_push (TV_JUMP);
rebuild_jump_labels (get_insns ());
cleanup_cfg (0);
timevar_pop (TV_JUMP);
}
+ else if (tem2 == 1)
+ cleanup_cfg (0);
flag_cse_skip_blocks = save_csb;
flag_cse_follow_jumps = save_cfj;
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_df_finish |
+ TODO_df_finish | TODO_verify_rtl_sharing |
TODO_dump_func |
TODO_verify_flow | TODO_ggc_collect, /* todo_flags_finish */
'G' /* letter */