aboutsummaryrefslogtreecommitdiff
path: root/gcc/dse.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2009-04-24 08:58:02 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2009-04-24 08:58:02 +0200
commit6216f94e37db8de5a846c5945f4aa5f4e32aaedf (patch)
treeb915c002276568ad8d30cd5e3340544d674fc103 /gcc/dse.c
parent6de7a512f0e76268d8ff69e51be80527c58d854b (diff)
downloadgcc-6216f94e37db8de5a846c5945f4aa5f4e32aaedf.zip
gcc-6216f94e37db8de5a846c5945f4aa5f4e32aaedf.tar.gz
gcc-6216f94e37db8de5a846c5945f4aa5f4e32aaedf.tar.bz2
re PR rtl-optimization/39794 (Miscompile with -O2 -funroll-loops)
PR rtl-optimization/39794 * alias.c (canon_true_dependence): Add x_addr argument. * rtl.h (canon_true_dependence): Adjust prototype. * cse.c (check_dependence): Adjust canon_true_dependence callers. * cselib.c (cselib_invalidate_mem): Likewise. * gcse.c (compute_transp): Likewise. * dse.c (scan_reads_nospill): Likewise. (record_store, check_mem_read_rtx): Likewise. For non-const-or-frame addresses pass base->val_rtx as mem_addr, for const-or-frame addresses canon_base_addr of the group, plus optional offset. (struct group_info): Rename canon_base_mem to canon_base_addr. (get_group_info): Set canon_base_addr to canon_rtx of base, not canon_rtx of base_mem. * gcc.dg/pr39794.c: New test. From-SVN: r146669
Diffstat (limited to 'gcc/dse.c')
-rw-r--r--gcc/dse.c64
1 files changed, 49 insertions, 15 deletions
diff --git a/gcc/dse.c b/gcc/dse.c
index e0e685b..5ac898c 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -223,7 +223,7 @@ struct store_info
/* This canonized mem. */
rtx mem;
- /* The result of get_addr on mem. */
+ /* Canonized MEM address for use by canon_true_dependence. */
rtx mem_addr;
/* If this is non-zero, it is the alias set of a spill location. */
@@ -476,8 +476,8 @@ struct group_info
do read dependency. */
rtx base_mem;
- /* Canonized version of base_mem, most likely the same thing. */
- rtx canon_base_mem;
+ /* Canonized version of base_mem's address. */
+ rtx canon_base_addr;
/* These two sets of two bitmaps are used to keep track of how many
stores are actually referencing that position from this base. We
@@ -705,7 +705,7 @@ get_group_info (rtx base)
gi->rtx_base = base;
gi->id = rtx_group_next_id++;
gi->base_mem = gen_rtx_MEM (QImode, base);
- gi->canon_base_mem = canon_rtx (gi->base_mem);
+ gi->canon_base_addr = canon_rtx (base);
gi->store1_n = BITMAP_ALLOC (NULL);
gi->store1_p = BITMAP_ALLOC (NULL);
gi->store2_n = BITMAP_ALLOC (NULL);
@@ -1286,7 +1286,7 @@ static rtx get_stored_val (store_info_t, enum machine_mode, HOST_WIDE_INT,
static int
record_store (rtx body, bb_info_t bb_info)
{
- rtx mem, rhs, const_rhs;
+ rtx mem, rhs, const_rhs, mem_addr;
HOST_WIDE_INT offset = 0;
HOST_WIDE_INT width = 0;
alias_set_type spill_alias_set;
@@ -1456,6 +1456,23 @@ record_store (rtx body, bb_info_t bb_info)
ptr = active_local_stores;
last = NULL;
redundant_reason = NULL;
+ mem = canon_rtx (mem);
+ /* For alias_set != 0 canon_true_dependence should be never called. */
+ if (spill_alias_set)
+ mem_addr = NULL_RTX;
+ else
+ {
+ if (group_id < 0)
+ mem_addr = base->val_rtx;
+ else
+ {
+ group_info_t group
+ = VEC_index (group_info_t, rtx_group_vec, group_id);
+ mem_addr = group->canon_base_addr;
+ }
+ if (offset)
+ mem_addr = plus_constant (mem_addr, offset);
+ }
while (ptr)
{
@@ -1547,13 +1564,13 @@ record_store (rtx body, bb_info_t bb_info)
if (canon_true_dependence (s_info->mem,
GET_MODE (s_info->mem),
s_info->mem_addr,
- mem, rtx_varies_p))
+ mem, mem_addr, rtx_varies_p))
{
s_info->rhs = NULL;
s_info->const_rhs = NULL;
}
}
-
+
/* An insn can be deleted if every position of every one of
its s_infos is zero. */
if (any_positions_needed_p (s_info)
@@ -1580,9 +1597,9 @@ record_store (rtx body, bb_info_t bb_info)
/* Finish filling in the store_info. */
store_info->next = insn_info->store_rec;
insn_info->store_rec = store_info;
- store_info->mem = canon_rtx (mem);
+ store_info->mem = mem;
store_info->alias_set = spill_alias_set;
- store_info->mem_addr = get_addr (XEXP (mem, 0));
+ store_info->mem_addr = mem_addr;
store_info->cse_base = base;
if (width > HOST_BITS_PER_WIDE_INT)
{
@@ -2006,7 +2023,7 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
static int
check_mem_read_rtx (rtx *loc, void *data)
{
- rtx mem = *loc;
+ rtx mem = *loc, mem_addr;
bb_info_t bb_info;
insn_info_t insn_info;
HOST_WIDE_INT offset = 0;
@@ -2058,6 +2075,22 @@ check_mem_read_rtx (rtx *loc, void *data)
read_info->end = offset + width;
read_info->next = insn_info->read_rec;
insn_info->read_rec = read_info;
+ /* For alias_set != 0 canon_true_dependence should be never called. */
+ if (spill_alias_set)
+ mem_addr = NULL_RTX;
+ else
+ {
+ if (group_id < 0)
+ mem_addr = base->val_rtx;
+ else
+ {
+ group_info_t group
+ = VEC_index (group_info_t, rtx_group_vec, group_id);
+ mem_addr = group->canon_base_addr;
+ }
+ if (offset)
+ mem_addr = plus_constant (mem_addr, offset);
+ }
/* We ignore the clobbers in store_info. The is mildly aggressive,
but there really should not be a clobber followed by a read. */
@@ -2128,7 +2161,7 @@ check_mem_read_rtx (rtx *loc, void *data)
= canon_true_dependence (store_info->mem,
GET_MODE (store_info->mem),
store_info->mem_addr,
- mem, rtx_varies_p);
+ mem, mem_addr, rtx_varies_p);
else if (group_id == store_info->group_id)
{
@@ -2139,7 +2172,7 @@ check_mem_read_rtx (rtx *loc, void *data)
= canon_true_dependence (store_info->mem,
GET_MODE (store_info->mem),
store_info->mem_addr,
- mem, rtx_varies_p);
+ mem, mem_addr, rtx_varies_p);
/* If this read is just reading back something that we just
stored, rewrite the read. */
@@ -2224,7 +2257,7 @@ check_mem_read_rtx (rtx *loc, void *data)
remove = canon_true_dependence (store_info->mem,
GET_MODE (store_info->mem),
store_info->mem_addr,
- mem, rtx_varies_p);
+ mem, mem_addr, rtx_varies_p);
if (remove)
{
@@ -3066,8 +3099,9 @@ scan_reads_nospill (insn_info_t insn_info, bitmap gen, bitmap kill)
if ((read_info->group_id < 0)
&& canon_true_dependence (group->base_mem,
QImode,
- group->canon_base_mem,
- read_info->mem, rtx_varies_p))
+ group->canon_base_addr,
+ read_info->mem, NULL_RTX,
+ rtx_varies_p))
{
if (kill)
bitmap_ior_into (kill, group->group_kill);