aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr111137.c30
-rw-r--r--gcc/tree-vect-data-refs.cc64
2 files changed, 77 insertions, 17 deletions
diff --git a/gcc/testsuite/gcc.dg/torture/pr111137.c b/gcc/testsuite/gcc.dg/torture/pr111137.c
new file mode 100644
index 0000000..7756048
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr111137.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+
+int b[3][8];
+short d;
+volatile int t = 1;
+
+void __attribute__((noipa))
+foo()
+{
+ int g = t;
+ for (int e = 1; e >= 0; e--)
+ {
+ d = 1;
+ for (; d >= 0; d--)
+ {
+ b[0][d * 2 + 1] = 0;
+ b[g - 1 + d][0] ^= 1;
+ b[0][d * 2 + 2] = 0;
+ b[g - 1 + d][1] ^= 1;
+ }
+ }
+}
+
+int
+main()
+{
+ foo ();
+ if (b[0][1] != 1)
+ __builtin_abort();
+}
diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index 0295e25..40ab568 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -750,6 +750,7 @@ vect_slp_analyze_load_dependences (vec_info *vinfo, slp_tree node,
data_reference *dr_a = STMT_VINFO_DATA_REF (access_info);
ao_ref ref;
bool ref_initialized_p = false;
+ hash_set<stmt_vec_info> grp_visited;
for (gimple_stmt_iterator gsi = gsi_for_stmt (access_info->stmt);
gsi_stmt (gsi) != first_access_info->stmt; gsi_prev (&gsi))
{
@@ -782,26 +783,55 @@ vect_slp_analyze_load_dependences (vec_info *vinfo, slp_tree node,
continue;
}
- /* We are hoisting a load - this means we can use TBAA for
- disambiguation. */
- if (!ref_initialized_p)
- ao_ref_init (&ref, DR_REF (dr_a));
- if (stmt_may_clobber_ref_p_1 (stmt, &ref, true))
+ auto check_hoist = [&] (stmt_vec_info stmt_info) -> bool
{
- /* If we couldn't record a (single) data reference for this
- stmt we have to give up now. */
- data_reference *dr_b = STMT_VINFO_DATA_REF (stmt_info);
- if (!dr_b)
- return false;
- ddr_p ddr = initialize_data_dependence_relation (dr_a,
- dr_b, vNULL);
- bool dependent
- = vect_slp_analyze_data_ref_dependence (vinfo, ddr);
- free_dependence_relation (ddr);
- if (dependent)
+ /* We are hoisting a load - this means we can use TBAA for
+ disambiguation. */
+ if (!ref_initialized_p)
+ ao_ref_init (&ref, DR_REF (dr_a));
+ if (stmt_may_clobber_ref_p_1 (stmt_info->stmt, &ref, true))
+ {
+ /* If we couldn't record a (single) data reference for this
+ stmt we have to give up now. */
+ data_reference *dr_b = STMT_VINFO_DATA_REF (stmt_info);
+ if (!dr_b)
+ return false;
+ ddr_p ddr = initialize_data_dependence_relation (dr_a,
+ dr_b, vNULL);
+ bool dependent
+ = vect_slp_analyze_data_ref_dependence (vinfo, ddr);
+ free_dependence_relation (ddr);
+ if (dependent)
+ return false;
+ }
+ /* No dependence. */
+ return true;
+ };
+ if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
+ {
+ /* When we run into a store group we have to honor
+ that earlier stores might be moved here. We don't
+ know exactly which and where to since we lack a
+ back-mapping from DR to SLP node, so assume all
+ earlier stores are sunk here. It's enough to
+ consider the last stmt of a group for this.
+ ??? Both this and the fact that we disregard that
+ the conflicting instance might be removed later
+ is overly conservative. */
+ if (!grp_visited.add (DR_GROUP_FIRST_ELEMENT (stmt_info)))
+ for (auto store_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ store_info != NULL;
+ store_info = DR_GROUP_NEXT_ELEMENT (store_info))
+ if ((store_info == stmt_info
+ || get_later_stmt (store_info, stmt_info) == stmt_info)
+ && !check_hoist (store_info))
+ return false;
+ }
+ else
+ {
+ if (!check_hoist (stmt_info))
return false;
}
- /* No dependence. */
}
}
return true;