diff options
author | Jakub Jelinek <jakub@redhat.com> | 2009-04-24 08:58:02 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2009-04-24 08:58:02 +0200 |
commit | 6216f94e37db8de5a846c5945f4aa5f4e32aaedf (patch) | |
tree | b915c002276568ad8d30cd5e3340544d674fc103 /gcc | |
parent | 6de7a512f0e76268d8ff69e51be80527c58d854b (diff) | |
download | gcc-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')
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/alias.c | 10 | ||||
-rw-r--r-- | gcc/cse.c | 2 | ||||
-rw-r--r-- | gcc/cselib.c | 4 | ||||
-rw-r--r-- | gcc/dse.c | 64 | ||||
-rw-r--r-- | gcc/gcse.c | 4 | ||||
-rw-r--r-- | gcc/rtl.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr39794.c | 33 |
9 files changed, 115 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 042c56c..a96520a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +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): diff --git a/gcc/alias.c b/gcc/alias.c index acfd934..8a20f46 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -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; diff --git a/gcc/cselib.c b/gcc/cselib.c index 945a4a1..b040231 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -1,6 +1,6 @@ /* 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); @@ -1,7 +1,7 @@ /* 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 47f4a80..bb5ffce 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +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. diff --git a/gcc/testsuite/gcc.dg/pr39794.c b/gcc/testsuite/gcc.dg/pr39794.c new file mode 100644 index 0000000..2702ba7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr39794.c @@ -0,0 +1,33 @@ +/* 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; +} |