summaryrefslogtreecommitdiff
path: root/gcc/dse.c
diff options
context:
space:
mode:
authorzadeck <zadeck@138bc75d-0d04-0410-961f-82ee72b054a4>2008-12-18 13:38:39 +0000
committerzadeck <zadeck@138bc75d-0d04-0410-961f-82ee72b054a4>2008-12-18 13:38:39 +0000
commita1b0a968ee7123151335f60c9a9b82bc212fa403 (patch)
treec64daed76d865d25eb4ef4c4e020e357ce13e831 /gcc/dse.c
parent9c5786bd5e85945c2b68fac9b447e4db0103fe0d (diff)
downloadgcc-a1b0a968ee7123151335f60c9a9b82bc212fa403.tar.gz
2008-12-18 Kenneth Zadeck <zadeck@naturalbridge.com>
PR rtl-optimization/37922 * dse.c (bb_info): Added regs_live field. (look_for_hardregs): New function. (replace_read): Added regs_live parameter and code to check that shift sequence does not clobber live hardregs. (check_mem_read_rtx): Added parameter to replace_read. (dse_step1): Added regs_live bitmap and initialize it. (rest_of_handle_dse): Added DF_NOTES problem and earlier call to df_analyze. * df-problems.c Renamed to df_simulate_initialize_backwards. (df_simulate_one_insn): Renamed to df_simulate_one_insn_backwards. (df_simulate_artificial_refs_at_top): Renamed to df_simulate_finalize_backwards. (df_simulate_initialized_forwards, df_simulate_one_insn_forwards, df_simulate_finalize_backwards): New functions. * df.h (df_simulate_artificial_refs_at_end): Renamed to df_simulate_initialize_backwards. (df_simulate_one_insn): Renamed to df_simulate_one_insn_backwards. (df_simulate_artificial_refs_at_top): Renamed to df_simulate_finalize_backwards. (df_simulate_initialized_forwards, df_simulate_one_insn_forwards, df_simulate_finalize_backwards): New functions. * ra-conflict.c (global_conflicts): Renamed df_simulate_artificial_refs_at_end to df_simulate_initialize_backwards. * sel-sched.c (propagate_lv_set): Renamed df_simulate_one_insn to df_simulate_one_insn_backwards. * ifcvt.c (dead_or_predicable): Renamed df_simulate_artificial_refs_at_end to df_simulate_initialize_backwards. Renamed df_simulate_one_insn to df_simulate_one_insn_backwards. * recog.c (peephole2_optimize): Ditto. * rtl-factoring (collect_pattern_seqs, clear_regs_live_in_seq): Ditto. 2008-12-18 Kenneth Zadeck <zadeck@naturalbridge.com> PR rtl-optimization/37922 * g++.dg/torture/pr37922.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@142809 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/dse.c')
-rw-r--r--gcc/dse.c83
1 files changed, 78 insertions, 5 deletions
diff --git a/gcc/dse.c b/gcc/dse.c
index d7fb2d8aa20..3269c7adaff 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -374,6 +374,10 @@ struct bb_info
operations. */
bool apply_wild_read;
+ /* The following 4 bitvectors hold information about which positions
+ of which stores are live or dead. They are indexed by
+ get_bitmap_index. */
+
/* The set of store positions that exist in this block before a wild read. */
bitmap gen;
@@ -401,6 +405,14 @@ struct bb_info
just initializes the vector from one of the out sets of the
successors of the block. */
bitmap out;
+
+ /* The following bitvector is indexed by the reg number. It
+ contains the set of regs that are live at the current instruction
+ being processed. While it contains info for all of the
+ registers, only the pseudos are actually examined. It is used to
+ assure that shift sequences that are inserted do not accidently
+ clobber live hard regs. */
+ bitmap regs_live;
};
typedef struct bb_info *bb_info_t;
@@ -1533,6 +1545,25 @@ find_shift_sequence (int access_size,
}
+/* Call back for note_stores to find the hard regs set or clobbered by
+ insn. Data is a bitmap of the hardregs set so far. */
+
+static void
+look_for_hardregs (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
+{
+ bitmap regs_set = (bitmap) data;
+
+ if (REG_P (x)
+ && REGNO (x) < FIRST_PSEUDO_REGISTER)
+ {
+ int regno = REGNO (x);
+ int n = hard_regno_nregs[regno][GET_MODE (x)];
+ while (--n >= 0)
+ bitmap_set_bit (regs_set, regno + n);
+ }
+}
+
+
/* Take a sequence of:
A <- r1
...
@@ -1566,13 +1597,13 @@ find_shift_sequence (int access_size,
static bool
replace_read (store_info_t store_info, insn_info_t store_insn,
- read_info_t read_info, insn_info_t read_insn, rtx *loc)
+ read_info_t read_info, insn_info_t read_insn, rtx *loc, bitmap regs_live)
{
enum machine_mode store_mode = GET_MODE (store_info->mem);
enum machine_mode read_mode = GET_MODE (read_info->mem);
int shift;
int access_size; /* In bytes. */
- rtx insns, read_reg;
+ rtx insns, this_insn, read_reg;
if (!dbg_cnt (dse))
return false;
@@ -1624,6 +1655,34 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
insns = get_insns ();
end_sequence ();
+ if (insns != NULL_RTX)
+ {
+ /* Now we have to scan the set of new instructions to see if the
+ sequence contains and sets of hardregs that happened to be
+ live at this point. For instance, this can happen if one of
+ the insns sets the CC and the CC happened to be live at that
+ point. This does occasionally happen, see PR 37922. */
+ bitmap regs_set = BITMAP_ALLOC (NULL);
+
+ for (this_insn = insns; this_insn != NULL_RTX; this_insn = NEXT_INSN (this_insn))
+ note_stores (PATTERN (this_insn), look_for_hardregs, regs_set);
+
+ bitmap_and_into (regs_set, regs_live);
+ if (!bitmap_empty_p (regs_set))
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file,
+ "abandoning replacement because sequence clobbers live hardregs:");
+ df_print_regset (dump_file, regs_set);
+ }
+
+ BITMAP_FREE (regs_set);
+ return false;
+ }
+ BITMAP_FREE (regs_set);
+ }
+
if (validate_change (read_insn->insn, loc, read_reg, 0))
{
deferred_change_t deferred_change =
@@ -1842,7 +1901,7 @@ check_mem_read_rtx (rtx *loc, void *data)
if ((store_info->positions_needed & mask) == mask
&& replace_read (store_info, i_ptr,
- read_info, insn_info, loc))
+ read_info, insn_info, loc, bb_info->regs_live))
return 0;
}
/* The bases are the same, just see if the offsets
@@ -1911,7 +1970,7 @@ check_mem_read_rtx (rtx *loc, void *data)
if ((store_info->positions_needed & mask) == mask
&& replace_read (store_info, i_ptr,
- read_info, insn_info, loc))
+ read_info, insn_info, loc, bb_info->regs_live))
return 0;
}
@@ -2139,7 +2198,8 @@ static void
dse_step1 (void)
{
basic_block bb;
-
+ bitmap regs_live = BITMAP_ALLOC (NULL);
+
cselib_init (false);
all_blocks = BITMAP_ALLOC (NULL);
bitmap_set_bit (all_blocks, ENTRY_BLOCK);
@@ -2152,6 +2212,10 @@ dse_step1 (void)
memset (bb_info, 0, sizeof (struct bb_info));
bitmap_set_bit (all_blocks, bb->index);
+ bb_info->regs_live = regs_live;
+
+ bitmap_copy (regs_live, DF_LR_IN (bb));
+ df_simulate_initialize_forwards (bb, regs_live);
bb_table[bb->index] = bb_info;
cselib_discard_hook = remove_useless_values;
@@ -2172,6 +2236,8 @@ dse_step1 (void)
if (INSN_P (insn))
scan_insn (bb_info, insn);
cselib_process_insn (insn);
+ if (INSN_P (insn))
+ df_simulate_one_insn_forwards (bb, insn, regs_live);
}
/* This is something of a hack, because the global algorithm
@@ -2238,8 +2304,10 @@ dse_step1 (void)
free_alloc_pool (cse_store_info_pool);
}
+ bb_info->regs_live = NULL;
}
+ BITMAP_FREE (regs_live);
cselib_finish ();
htab_empty (rtx_group_table);
}
@@ -3239,6 +3307,11 @@ rest_of_handle_dse (void)
df_set_flags (DF_DEFER_INSN_RESCAN);
+ /* Need the notes since we must track live hardregs in the forwards
+ direction. */
+ df_note_add_problem ();
+ df_analyze ();
+
dse_step0 ();
dse_step1 ();
dse_step2_init ();