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 2, or (at your option) any later
+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
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* TODO
- reordering of memory allocation and freeing to be more space efficient
#include "timevar.h"
#include "tree-pass.h"
#include "hashtab.h"
+#include "df.h"
+#include "dbgcnt.h"
/* Propagate flow information through back edges and thus enable PRE's
moving loop invariant calculations out of loops.
static void alloc_reg_set_mem (int);
static void free_reg_set_mem (void);
static void record_one_set (int, rtx);
-static void record_set_info (rtx, rtx, void *);
+static void record_set_info (rtx, const_rtx, void *);
static void compute_sets (void);
static void hash_scan_insn (rtx, struct hash_table *, int);
static void hash_scan_set (rtx, rtx, struct hash_table *);
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, rtx, void *);
+static void record_last_set_info (rtx, const_rtx, void *);
static void compute_hash_table (struct hash_table *);
static void alloc_hash_table (int, struct hash_table *, int);
static void free_hash_table (struct hash_table *);
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 int try_replace_reg (rtx, rtx, rtx);
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, rtx, void *);
-static int load_killed_in_block_p (basic_block, int, rtx, int);
-static void canon_list_insert (rtx, rtx, void *);
+static void mems_conflict_for_gcse_p (rtx, const_rtx, void *);
+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 void find_implicit_sets (void);
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 void compute_pre_data (void);
static int pre_expr_reaches_here_p (basic_block, struct expr *,
basic_block);
-static void insert_insn_end_bb (struct expr *, basic_block, int);
+static void insert_insn_end_basic_block (struct expr *, basic_block, int);
static void pre_insert_copy_insn (struct expr *, rtx);
static void pre_insert_copies (void);
static int pre_delete (void);
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, rtx, void *);
-static void reg_clear_last_set (rtx, rtx, void *);
-static bool store_ops_ok (rtx, int *);
+static void reg_set_info (rtx, const_rtx, void *);
+static void reg_clear_last_set (rtx, const_rtx, void *);
+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_bb (rtx, basic_block);
+static void insert_insn_start_basic_block (rtx, basic_block);
static int insert_store (struct ls_expr *, edge);
static void remove_reachable_equiv_notes (basic_block, struct ls_expr *);
static void replace_store_insn (rtx, rtx, basic_block, struct ls_expr *);
successors and predecessors. */
max_gcse_regno = max_reg_num ();
+ df_note_add_problem ();
+ df_analyze ();
+
if (dump_file)
dump_flow_info (dump_file, dump_flags);
alloc_gcse_mem ();
/* This time, go ahead and allow cprop to alter jumps. */
timevar_push (TV_CPROP2);
- one_cprop_pass (pass + 1, true, false);
+ one_cprop_pass (pass + 1, true, true);
timevar_pop (TV_CPROP2);
free_gcse_mem ();
/* We are finished with alias. */
end_alias_analysis ();
- allocate_reg_info (max_reg_num (), FALSE, FALSE);
if (!optimize_size && flag_gcse_sm)
{
occurring. */
static void
-record_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, void *data)
+record_set_info (rtx dest, const_rtx setter ATTRIBUTE_UNUSED, void *data)
{
rtx record_set_insn = (rtx) data;
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
gcse_mems_conflict_p to a nonzero value. */
static void
-mems_conflict_for_gcse_p (rtx dest, rtx setter ATTRIBUTE_UNUSED,
+mems_conflict_for_gcse_p (rtx dest, const_rtx setter ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
while (GET_CODE (dest) == SUBREG
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
{
/* An expression is not anticipatable if its operands are
modified before this insn or if this is not the only SET in
- this insn. */
- int antic_p = oprs_anticipatable_p (src, insn) && single_set (insn);
+ this insn. The latter condition does not have to mean that
+ SRC itself is not anticipatable, but we just will not be
+ able to handle code motion of insns with multiple sets. */
+ int antic_p = oprs_anticipatable_p (src, insn)
+ && !multiple_sets (insn);
/* An expression is not available if its operands are
subsequently modified, including this insn. It's also not
available if this is a branch, because we can't insert
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
+ || 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
taken off pairwise. */
static void
-canon_list_insert (rtx dest ATTRIBUTE_UNUSED, rtx unused1 ATTRIBUTE_UNUSED,
+canon_list_insert (rtx dest ATTRIBUTE_UNUSED, const_rtx unused1 ATTRIBUTE_UNUSED,
void * v_insn)
{
rtx dest_addr, insn;
the SET is taking place. */
static void
-record_last_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, void *data)
+record_last_set_info (rtx dest, const_rtx setter ATTRIBUTE_UNUSED, void *data)
{
rtx last_set_insn = (rtx) data;
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:
if (note != 0 && REG_NOTE_KIND (note) == REG_EQUAL)
set_unique_reg_note (insn, REG_EQUAL,
simplify_replace_rtx (XEXP (note, 0), from, 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
/* Remove REG_EQUAL note after simplification. */
if (note_src)
remove_note (jump, note);
-
- /* If this has turned into an unconditional jump,
- then put a barrier after it so that the unreachable
- code will be deleted. */
- if (GET_CODE (SET_SRC (set)) == LABEL_REF)
- emit_barrier_after (jump);
}
#ifdef HAVE_cc0
/* If we find a case where we can't fix the retval REG_EQUAL notes
match the new register, we either have to abandon this replacement
or fix delete_trivially_dead_insns to preserve the setting insn,
- or make it delete the REG_EUAQL note, and fix up all passes that
+ or make it delete the REG_EQUAL note, and fix up all passes that
require the REG_EQUAL note there. */
bool adjusted;
}
}
XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), oldreg, newval);
+ df_notes_rescan (end);
insn = end;
}
return true;
for (reg_used = ®_use_table[0]; reg_use_count > 0;
reg_used++, reg_use_count--)
- if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
- libcall_sp))
- {
- changed = true;
- break;
- }
+ {
+ if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
+ libcall_sp))
+ {
+ changed = true;
+ break;
+ }
+ }
if (INSN_DELETED_P (insn))
break;
}
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;
no sense for code hoisting. */
static void
-insert_insn_end_bb (struct expr *expr, basic_block bb, int pre)
+insert_insn_end_basic_block (struct expr *expr, basic_block bb, int pre)
{
rtx insn = BB_END (bb);
rtx new_insn;
}
#endif
/* FIXME: What if something in cc0/jump uses value set in new insn? */
- new_insn = emit_insn_before_noloc (pat, insn);
+ new_insn = emit_insn_before_noloc (pat, insn, bb);
}
/* Likewise if the last insn is a call, as will happen in the presence
|| NOTE_INSN_BASIC_BLOCK_P (insn))
insn = NEXT_INSN (insn);
- new_insn = emit_insn_before_noloc (pat, insn);
+ new_insn = emit_insn_before_noloc (pat, insn, bb);
}
else
- new_insn = emit_insn_after_noloc (pat, insn);
+ new_insn = emit_insn_after_noloc (pat, insn, bb);
while (1)
{
now. */
if (eg->flags & EDGE_ABNORMAL)
- insert_insn_end_bb (index_map[j], bb, 0);
+ insert_insn_end_basic_block (index_map[j], bb, 0);
else
{
insn = process_insert_insn (index_map[j]);
/* We only delete insns that have a single_set. */
if (TEST_BIT (pre_delete_map[bb->index], indx)
- && (set = single_set (insn)) != 0)
+ && (set = single_set (insn)) != 0
+ && dbg_cnt (pre_insn))
{
/* Create a pseudo-reg to store the result of reaching
expressions into. Get the mode for the new pseudo from
- we know which insns are redundant when we go to create copies */
changed = pre_delete ();
-
did_insert = pre_edge_insert (edge_list, index_map);
/* In other places with reaching expressions, copy the expression to the
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));
- if (LABEL_P (XEXP (x, 0)))
- LABEL_NUSES (XEXP (x, 0))++;
+ if (reg_mentioned_p (XEXP (x, 0), 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;
}
hoist_code (void)
{
basic_block bb, dominated;
- basic_block *domby;
- unsigned int domby_len;
+ VEC (basic_block, heap) *domby;
unsigned int i,j;
struct expr **index_map;
struct expr *expr;
int found = 0;
int insn_inserted_p;
- domby_len = get_dominated_by (CDI_DOMINATORS, bb, &domby);
+ domby = get_dominated_by (CDI_DOMINATORS, bb);
/* Examine each expression that is very busy at the exit of this
block. These are the potentially hoistable expressions. */
for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++)
/* We've found a potentially hoistable expression, now
we look at every block BB dominates to see if it
computes the expression. */
- for (j = 0; j < domby_len; j++)
+ for (j = 0; VEC_iterate (basic_block, domby, j, dominated); j++)
{
- dominated = domby[j];
/* Ignore self dominance. */
if (bb == dominated)
continue;
/* If we found nothing to hoist, then quit now. */
if (! found)
{
- free (domby);
- continue;
+ VEC_free (basic_block, heap, domby);
+ continue;
}
/* Loop over all the hoistable expressions. */
/* We've found a potentially hoistable expression, now
we look at every block BB dominates to see if it
computes the expression. */
- for (j = 0; j < domby_len; j++)
+ for (j = 0; VEC_iterate (basic_block, domby, j, dominated); j++)
{
- dominated = domby[j];
/* Ignore self dominance. */
if (bb == dominated)
continue;
occr->deleted_p = 1;
if (!insn_inserted_p)
{
- insert_insn_end_bb (index_map[i], bb, 0);
+ insert_insn_end_basic_block (index_map[i], bb, 0);
insn_inserted_p = 1;
}
}
}
}
}
- free (domby);
+ VEC_free (basic_block, heap, domby);
}
free (index_map);
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;
new = emit_insn_before (copy, insn);
record_one_set (REGNO (reg), new);
SET_SRC (pat) = reg;
+ df_insn_rescan (insn);
/* un-recognize this pattern since it's probably different now. */
INSN_CODE (insn) = -1;
note_stores. */
static void
-reg_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED,
+reg_set_info (rtx dest, const_rtx setter ATTRIBUTE_UNUSED,
void *data)
{
sbitmap bb_reg = data;
note_stores. */
static void
-reg_clear_last_set (rtx dest, rtx setter ATTRIBUTE_UNUSED,
+reg_clear_last_set (rtx dest, const_rtx setter ATTRIBUTE_UNUSED,
void *data)
{
int *dead_vec = data;
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 PRE_DEC:
case PRE_INC:
+ case PRE_MODIFY:
case POST_DEC:
case POST_INC:
+ case POST_MODIFY:
/* We do not run this function with arguments having side effects. */
gcc_unreachable ();
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;
return ret;
}
+static inline bool
+store_killed_in_pat (const_rtx x, const_rtx pat, int after)
+{
+ if (GET_CODE (pat) == SET)
+ {
+ rtx dest = SET_DEST (pat);
+
+ if (GET_CODE (dest) == ZERO_EXTRACT)
+ dest = XEXP (dest, 0);
+
+ /* Check for memory stores to aliased objects. */
+ if (MEM_P (dest)
+ && !expr_equiv_p (dest, x))
+ {
+ if (after)
+ {
+ if (output_dependence (dest, x))
+ return true;
+ }
+ else
+ {
+ if (output_dependence (x, dest))
+ return true;
+ }
+ }
+ }
+
+ if (find_loads (pat, x, after))
+ return true;
+
+ return false;
+}
+
/* Check if INSN kills the store pattern X (is aliased with it).
AFTER is true if we are checking the case when store X occurs
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;
+ const_rtx reg, base, note, pat;
if (!INSN_P (insn))
return false;
return false;
}
- if (GET_CODE (PATTERN (insn)) == SET)
+ pat = PATTERN (insn);
+ if (GET_CODE (pat) == SET)
{
- rtx pat = PATTERN (insn);
- rtx dest = SET_DEST (pat);
-
- if (GET_CODE (dest) == ZERO_EXTRACT)
- dest = XEXP (dest, 0);
-
- /* Check for memory stores to aliased objects. */
- if (MEM_P (dest)
- && !expr_equiv_p (dest, x))
- {
- if (after)
- {
- if (output_dependence (dest, x))
- return true;
- }
- else
- {
- if (output_dependence (x, dest))
- return true;
- }
- }
- if (find_loads (SET_SRC (pat), x, after))
+ if (store_killed_in_pat (x, pat, after))
return true;
}
+ else if (GET_CODE (pat) == PARALLEL)
+ {
+ int i;
+
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ if (store_killed_in_pat (x, XVECEXP (pat, 0, i), after))
+ return true;
+ }
else if (find_loads (PATTERN (insn), x, after))
return true;
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);
the BB_HEAD if needed. */
static void
-insert_insn_start_bb (rtx insn, basic_block bb)
+insert_insn_start_basic_block (rtx insn, basic_block bb)
{
/* Insert at start of successor block. */
rtx prev = PREV_INSN (BB_HEAD (bb));
while (before != 0)
{
if (! LABEL_P (before)
- && (! NOTE_P (before)
- || NOTE_LINE_NUMBER (before) != NOTE_INSN_BASIC_BLOCK))
+ && !NOTE_INSN_BASIC_BLOCK_P (before))
break;
prev = before;
if (prev == BB_END (bb))
before = NEXT_INSN (before);
}
- insn = emit_insn_after_noloc (insn, prev);
+ insn = emit_insn_after_noloc (insn, prev, bb);
if (dump_file)
{
int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
RESET_BIT (pre_insert_map[index], expr->index);
}
- insert_insn_start_bb (insn, bb);
+ insert_insn_start_basic_block (insn, bb);
return 0;
}
mem = smexpr->pattern;
insn = gen_move_insn (reg, SET_SRC (single_set (del)));
- insn = emit_insn_after (insn, del);
-
- if (dump_file)
- {
- fprintf (dump_file,
- "STORE_MOTION delete insn in BB %d:\n ", bb->index);
- print_inline_rtx (dump_file, del, 6);
- fprintf (dump_file, "\nSTORE MOTION replaced with insn:\n ");
- print_inline_rtx (dump_file, insn, 6);
- fprintf (dump_file, "\n");
- }
for (ptr = ANTIC_STORE_LIST (smexpr); ptr; ptr = XEXP (ptr, 1))
if (XEXP (ptr, 0) == del)
XEXP (note, 0) = insn;
}
+ /* Emit the insn AFTER all the notes are transferred.
+ This is cheaper since we avoid df rescanning for the note change. */
+ insn = emit_insn_after (insn, del);
+
+ if (dump_file)
+ {
+ fprintf (dump_file,
+ "STORE_MOTION delete insn in BB %d:\n ", bb->index);
+ print_inline_rtx (dump_file, del, 6);
+ fprintf (dump_file, "\nSTORE MOTION replaced with insn:\n ");
+ print_inline_rtx (dump_file, insn, 6);
+ fprintf (dump_file, "\n");
+ }
+
delete_insn (del);
/* Now we must handle REG_EQUAL notes whose contents is equal to the mem;
/* We are finished with alias. */
end_alias_analysis ();
- allocate_reg_info (max_reg_num (), FALSE, FALSE);
return changed;
}
static unsigned int
rest_of_handle_jump_bypass (void)
{
- cleanup_cfg (CLEANUP_EXPENSIVE);
- reg_scan (get_insns (), max_reg_num ());
-
+ delete_unreachable_blocks ();
if (bypass_jumps ())
{
- rebuild_jump_labels (get_insns ());
- cleanup_cfg (CLEANUP_EXPENSIVE);
delete_trivially_dead_insns (get_insns (), max_reg_num ());
+ rebuild_jump_labels (get_insns ());
+ cleanup_cfg (0);
}
return 0;
}
{
int save_csb, save_cfj;
int tem2 = 0, tem;
-
tem = gcse_main (get_insns ());
- rebuild_jump_labels (get_insns ());
delete_trivially_dead_insns (get_insns (), max_reg_num ());
-
+ rebuild_jump_labels (get_insns ());
save_csb = flag_cse_skip_blocks;
save_cfj = flag_cse_follow_jumps;
flag_cse_skip_blocks = flag_cse_follow_jumps = 0;
if (flag_expensive_optimizations)
{
timevar_push (TV_CSE);
- reg_scan (get_insns (), max_reg_num ());
tem2 = cse_main (get_insns (), max_reg_num ());
+ df_finish_pass (false);
purge_all_dead_edges ();
delete_trivially_dead_insns (get_insns (), max_reg_num ());
timevar_pop (TV_CSE);
{
timevar_push (TV_JUMP);
rebuild_jump_labels (get_insns ());
- delete_dead_jumptables ();
- cleanup_cfg (CLEANUP_EXPENSIVE);
+ cleanup_cfg (0);
timevar_pop (TV_JUMP);
}
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
+ TODO_df_finish | TODO_verify_rtl_sharing |
TODO_dump_func |
TODO_verify_flow | TODO_ggc_collect, /* todo_flags_finish */
'G' /* letter */