aboutsummaryrefslogtreecommitdiff
path: root/gcc/dce.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-04-12 18:20:21 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2019-04-12 18:20:21 +0200
commit76416d899cb6d26088a9cd22da5a23914fec2ce6 (patch)
treeec74ffabc483a16790bb4ff7ba1f5782a5fcdad0 /gcc/dce.c
parentb2e77a37a2c4b8165c542c93966c4a3874fde817 (diff)
downloadgcc-76416d899cb6d26088a9cd22da5a23914fec2ce6.zip
gcc-76416d899cb6d26088a9cd22da5a23914fec2ce6.tar.gz
gcc-76416d899cb6d26088a9cd22da5a23914fec2ce6.tar.bz2
re PR rtl-optimization/89965 (wrong code with -O -mtune=nano-x2 -fcaller-saves -fexpensive-optimizations -fno-tree-dce -fno-tree-ter)
PR rtl-optimization/89965 * dce.c: Include rtl-iter.h. (struct check_argument_load_data): New type. (check_argument_load): New function. (find_call_stack_args): Check for loads from stack slots still tracked in sp_bytes and punt if any is found. * gcc.target/i386/pr89965.c: New test. From-SVN: r270323
Diffstat (limited to 'gcc/dce.c')
-rw-r--r--gcc/dce.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/gcc/dce.c b/gcc/dce.c
index 98063dc..e6822fe 100644
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "valtrack.h"
#include "tree-pass.h"
#include "dbgcnt.h"
+#include "rtl-iter.h"
/* -------------------------------------------------------------------------
@@ -325,6 +326,48 @@ sp_based_mem_offset (rtx_call_insn *call_insn, const_rtx mem, bool fast)
return off;
}
+/* Data for check_argument_load called via note_uses. */
+struct check_argument_load_data {
+ bitmap sp_bytes;
+ HOST_WIDE_INT min_sp_off, max_sp_off;
+ rtx_call_insn *call_insn;
+ bool fast;
+ bool load_found;
+};
+
+/* Helper function for find_call_stack_args. Check if there are
+ any loads from the argument slots in between the const/pure call
+ and store to the argument slot, set LOAD_FOUND if any is found. */
+
+static void
+check_argument_load (rtx *loc, void *data)
+{
+ struct check_argument_load_data *d
+ = (struct check_argument_load_data *) data;
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, *loc, NONCONST)
+ {
+ const_rtx mem = *iter;
+ HOST_WIDE_INT size;
+ if (MEM_P (mem)
+ && MEM_SIZE_KNOWN_P (mem)
+ && MEM_SIZE (mem).is_constant (&size))
+ {
+ HOST_WIDE_INT off = sp_based_mem_offset (d->call_insn, mem, d->fast);
+ if (off != INTTYPE_MINIMUM (HOST_WIDE_INT)
+ && off < d->max_sp_off
+ && off + size > d->min_sp_off)
+ for (HOST_WIDE_INT byte = MAX (off, d->min_sp_off);
+ byte < MIN (off + size, d->max_sp_off); byte++)
+ if (bitmap_bit_p (d->sp_bytes, byte - d->min_sp_off))
+ {
+ d->load_found = true;
+ return;
+ }
+ }
+ }
+}
+
/* Try to find all stack stores of CALL_INSN arguments if
ACCUMULATE_OUTGOING_ARGS. If all stack stores have been found
and it is therefore safe to eliminate the call, return true,
@@ -394,8 +437,10 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast,
}
/* Walk backwards, looking for argument stores. The search stops
- when seeing another call, sp adjustment or memory store other than
- argument store. */
+ when seeing another call, sp adjustment, memory store other than
+ argument store or a read from an argument stack slot. */
+ struct check_argument_load_data data
+ = { sp_bytes, min_sp_off, max_sp_off, call_insn, fast, false };
ret = false;
for (insn = PREV_INSN (call_insn); insn; insn = prev_insn)
{
@@ -414,6 +459,10 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast,
if (!set || SET_DEST (set) == stack_pointer_rtx)
break;
+ note_uses (&PATTERN (insn), check_argument_load, &data);
+ if (data.load_found)
+ break;
+
if (!MEM_P (SET_DEST (set)))
continue;