diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr111137.c | 30 | ||||
-rw-r--r-- | gcc/tree-vect-data-refs.cc | 64 |
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; |