Commit 6216f94e by Jakub Jelinek Committed by Jakub Jelinek

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
parent 6de7a512
2009-04-24 Jakub Jelinek <jakub@redhat.com>
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.
2009-04-23 Paolo Bonzini <bonzini@gnu.org>
* config/sh/sh.c (sh_expand_prologue, sh_expand_epilogue):
......
......@@ -2287,14 +2287,13 @@ true_dependence (const_rtx mem, enum machine_mode mem_mode, const_rtx x,
Variant of true_dependence which assumes MEM has already been
canonicalized (hence we no longer do that here).
The mem_addr argument has been added, since true_dependence computed
this value prior to canonicalizing. */
this value prior to canonicalizing.
If x_addr is non-NULL, it is used in preference of XEXP (x, 0). */
int
canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
const_rtx x, bool (*varies) (const_rtx, bool))
const_rtx x, rtx x_addr, bool (*varies) (const_rtx, bool))
{
rtx x_addr;
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
return 1;
......@@ -2320,7 +2319,8 @@ canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
if (nonoverlapping_memrefs_p (x, mem))
return 0;
x_addr = get_addr (XEXP (x, 0));
if (! x_addr)
x_addr = get_addr (XEXP (x, 0));
if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode))
return 0;
......
......@@ -1658,7 +1658,7 @@ check_dependence (rtx *x, void *data)
{
struct check_dependence_data *d = (struct check_dependence_data *) data;
if (*x && MEM_P (*x))
return canon_true_dependence (d->exp, d->mode, d->addr, *x,
return canon_true_dependence (d->exp, d->mode, d->addr, *x, NULL_RTX,
cse_rtx_varies_p);
else
return 0;
......
/* Common subexpression elimination library for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008
1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
......@@ -1483,7 +1483,7 @@ cselib_invalidate_mem (rtx mem_rtx)
}
if (num_mems < PARAM_VALUE (PARAM_MAX_CSELIB_MEMORY_LOCATIONS)
&& ! canon_true_dependence (mem_rtx, GET_MODE (mem_rtx), mem_addr,
x, cselib_rtx_varies_p))
x, NULL_RTX, cselib_rtx_varies_p))
{
has_mem = true;
num_mems++;
......
......@@ -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);
......
/* Global common subexpression elimination/Partial redundancy elimination
and global constant/copy propagation for GNU compiler.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008 Free Software Foundation, Inc.
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GCC.
......@@ -2512,7 +2512,7 @@ compute_transp (const_rtx x, int indx, sbitmap *bmap, int set_p)
dest_addr = XEXP (list_entry, 0);
if (canon_true_dependence (dest, GET_MODE (dest), dest_addr,
x, rtx_addr_varies_p))
x, NULL_RTX, rtx_addr_varies_p))
{
if (set_p)
SET_BIT (bmap[bb_index], indx);
......
......@@ -2290,7 +2290,7 @@ extern rtx canon_rtx (rtx);
extern int true_dependence (const_rtx, enum machine_mode, const_rtx, bool (*)(const_rtx, bool));
extern rtx get_addr (rtx);
extern int canon_true_dependence (const_rtx, enum machine_mode, rtx, const_rtx,
bool (*)(const_rtx, bool));
rtx, bool (*)(const_rtx, bool));
extern int read_dependence (const_rtx, const_rtx);
extern int anti_dependence (const_rtx, const_rtx);
extern int output_dependence (const_rtx, const_rtx);
......
2009-04-24 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/39794
* gcc.dg/pr39794.c: New test.
2009-04-23 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/atomic1.adb: New test.
......
/* PR rtl-optimization/39794 */
/* { dg-do run } */
/* { dg-options "-O2 -funroll-loops" } */
extern void abort ();
void
foo (int *a, int n)
{
int i;
for (i = 0; i < n; i++)
{
a[i] *= 2;
a[i + 1] = a[i - 1] + a[i - 2];
}
}
int a[16];
int ref[16] = { 0, 1, 4, 2, 10, 12, 24, 44,
72, 136, 232, 416, 736, 1296, 2304, 2032 };
int
main ()
{
int i;
for (i = 0; i < 16; i++)
a[i] = i;
foo (a + 2, 16 - 3);
for (i = 0; i < 16; i++)
if (ref[i] != a[i])
abort ();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment