aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2016-01-11 10:40:33 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2016-01-11 10:40:33 +0000
commitb4934671aed067e0a8c3ac3fcc5871dd27a706ed (patch)
treef256be24de028f3ba0f7322f307659ce87652c96 /gcc
parent4708731cceffa32a0bcddb8300147369299c4361 (diff)
downloadgcc-b4934671aed067e0a8c3ac3fcc5871dd27a706ed.zip
gcc-b4934671aed067e0a8c3ac3fcc5871dd27a706ed.tar.gz
gcc-b4934671aed067e0a8c3ac3fcc5871dd27a706ed.tar.bz2
[PR69123] fix handling of MEMs in VTA to avoid dataflow oscillation
The problem arises because we used to drop overwritten MEMs from loc lists of VALUEs, but not of other onepart variables, and it just so happens that, by doing so, block 6 in the testcase has no D#5 in its output in the first pass, because the MEM holding its (previous) value was correctly dropped from value 88:88, but gains it in the second pass because D#5 has the MEM location incoming directly in its loc list, rather than indirectly in a VALUE. This incorrect binding enables other blocks to believe they have a tentative binding for D#5 in some cycles, but others, still operating on the early conclusion, believe there isn't, and they oscillate from that. Since we check for escaping MEMs in clobbers, we won't lose anything relevant by dropping call-clobbered or overwritten MEMs in all onepart variables, and this ensures the loc intersection operation in onepart vars won't let a MEM through that wasn't present in earlier iterations. for gcc/ChangeLog PR bootstrap/69123 * var-tracking.c (drop_overlapping_mem_locs): Operate on all onepart vars. Fix typo in comment. Fix reversed condition in unshare test. (dataflow_set_remove_mem_locs): Operate on all onepart vars. for gcc/testsuite/ChangeLog PR bootstrap/69123 * g++.dg/pr69123.C: New. From-SVN: r232218
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/pr69123.C95
-rw-r--r--gcc/var-tracking.c12
4 files changed, 112 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9b1c41b..71aac8e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,12 @@
2016-01-11 Alexandre Oliva <aoliva@redhat.com>
PR bootstrap/69123
+ * var-tracking.c (drop_overlapping_mem_locs): Operate on all
+ onepart vars. Fix typo in comment. Fix reversed condition in
+ unshare test.
+ (dataflow_set_remove_mem_locs): Operate on all onepart vars.
+
+ PR bootstrap/69123
* var-tracking.c (dump_onepart_variable_differences): New.
(dataflow_set_different): If a detailed dump is requested,
delay early returns and dump differences between onepart
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cabef26..7095b45 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-01-11 Alexandre Oliva <aoliva@redhat.com>
+
+ PR bootstrap/69123
+ * g++.dg/pr69123.C: New.
+
2016-01-11 Ilya Enkovich <enkovich.gnu@gmail.com>
PR target/69010
diff --git a/gcc/testsuite/g++.dg/pr69123.C b/gcc/testsuite/g++.dg/pr69123.C
new file mode 100644
index 0000000..0546e20
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr69123.C
@@ -0,0 +1,95 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -g" } */
+
+/* This was reduced from gcc/tree-vect-slp.c by H.J.Lu. */
+
+struct xxx_def;
+typedef xxx_def *xxx;
+
+union rtxxx
+{
+ const char *rt_str;
+ xxx rt_xxx;
+};
+
+struct xxx_def {
+ union u {
+ rtxxx fld[1];
+ } u;
+};
+
+extern xxx bar (void);
+extern int foo1 (xxx);
+
+static inline xxx
+foo2 (xxx arg0, xxx arg1)
+{
+ xxx rt;
+ rt = bar ();
+ (((rt)->u.fld[0]).rt_xxx) = arg0;
+ (((rt)->u.fld[1]).rt_xxx) = arg1;
+ return rt;
+}
+
+static inline xxx
+foo4 (const char *arg0 )
+{
+ xxx rt;
+ rt = bar ();
+ (((rt)->u.fld[0]).rt_str) = arg0;
+ (((rt)->u.fld[1]).rt_xxx) = (xxx) 0;
+ return rt;
+}
+
+extern xxx foo5 (long);
+
+struct address_cost_data
+{
+ unsigned costs[2][2][2][2];
+};
+
+void
+get_address_cost (address_cost_data *data)
+{
+ unsigned acost;
+ long i;
+ long rat, off = 0;
+ unsigned sym_p, var_p, off_p, rat_p;
+ xxx addr, base;
+ xxx reg0, reg1;
+
+ reg1 = bar ();
+ addr = foo2 (reg1, (xxx) 0);
+ rat = 1;
+ acost = 0;
+ reg0 = bar ();
+ reg1 = bar ();
+
+ for (i = 0; i < 16; i++)
+ {
+ sym_p = i & 1;
+ var_p = (i >> 1) & 1;
+ off_p = (i >> 2) & 1;
+ rat_p = (i >> 3) & 1;
+
+ addr = reg0;
+ if (rat_p)
+ addr = foo2 (addr, foo5 (rat)) ;
+
+ if (var_p)
+ addr = foo2 (addr, reg1);
+
+ if (sym_p)
+ base = foo4 ("");
+ else if (off_p)
+ base = foo5 (off);
+ else
+ base = (xxx) 0;
+
+ if (base)
+ addr = foo2 (addr, base);
+
+ acost = foo1 (addr);
+ data->costs[sym_p][var_p][off_p][rat_p] = acost;
+ }
+}
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 023a73e..86183b3 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -2224,7 +2224,7 @@ struct overlapping_mems
};
/* Remove all MEMs that overlap with COMS->LOC from the location list
- of a hash table entry for a value. COMS->ADDR must be a
+ of a hash table entry for a onepart variable. COMS->ADDR must be a
canonicalized form of COMS->LOC's address, and COMS->LOC must be
canonicalized itself. */
@@ -2235,7 +2235,7 @@ drop_overlapping_mem_locs (variable **slot, overlapping_mems *coms)
rtx mloc = coms->loc, addr = coms->addr;
variable *var = *slot;
- if (var->onepart == ONEPART_VALUE)
+ if (var->onepart != NOT_ONEPART)
{
location_chain *loc, **locp;
bool changed = false;
@@ -4682,11 +4682,11 @@ dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set)
{
for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
{
- /* We want to remove dying MEMs that doesn't refer to DECL. */
+ /* We want to remove dying MEMs that don't refer to DECL. */
if (GET_CODE (loc->loc) == MEM
&& (MEM_EXPR (loc->loc) != decl
|| INT_MEM_OFFSET (loc->loc) != 0)
- && !mem_dies_at_call (loc->loc))
+ && mem_dies_at_call (loc->loc))
break;
/* We want to move here MEMs that do refer to DECL. */
else if (GET_CODE (loc->loc) == VALUE
@@ -4769,14 +4769,14 @@ dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set)
}
/* Remove all MEMs from the location list of a hash table entry for a
- value. */
+ onepart variable. */
int
dataflow_set_remove_mem_locs (variable **slot, dataflow_set *set)
{
variable *var = *slot;
- if (var->onepart == ONEPART_VALUE)
+ if (var->onepart != NOT_ONEPART)
{
location_chain *loc, **locp;
bool changed = false;