From: Richard Biener Date: Mon, 26 Nov 2018 13:31:21 +0000 (+0000) Subject: backport: [multiple changes] X-Git-Tag: releases/gcc-7.4.0~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a3ca04d3054b6fb6d3d98fac650d7df7ff490098;p=thirdparty%2Fgcc.git backport: [multiple changes] 2018-11-26 Richard Biener Backport from mainline 2018-10-15 Richard Biener PR middle-end/87610 * tree-ssa-structalias.c (struct vls_data): Add escaped_p member. (visit_loadstore): When a used restrict tag escaped verify that the points-to solution of "other" pointers do not include escaped. (compute_dependence_clique): If a used restrict tag escaped communicated that down to visit_loadstore. * gcc.dg/torture/restrict-6.c: New testcase. 2018-10-25 Richard Biener PR tree-optimization/87665 PR tree-optimization/87745 * tree-vectorizer.h (get_earlier_stmt): Remove. (get_later_stmt): Pick up UID from the original non-pattern stmt. * gfortran.dg/20181025-1.f: New testcase. 2018-10-24 Richard Biener PR tree-optimization/87665 * tree-vect-data-refs.c (vect_preserves_scalar_order_p): Adjust to reflect reality. * gcc.dg/torture/pr87665.c: New testcase. From-SVN: r266460 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d057e26662bf..77d3a77c399b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2018-11-26 Richard Biener + + Backport from mainline + 2018-10-15 Richard Biener + + PR middle-end/87610 + * tree-ssa-structalias.c (struct vls_data): Add escaped_p member. + (visit_loadstore): When a used restrict tag escaped verify that + the points-to solution of "other" pointers do not include + escaped. + (compute_dependence_clique): If a used restrict tag escaped + communicated that down to visit_loadstore. + + 2018-10-25 Richard Biener + + PR tree-optimization/87665 + PR tree-optimization/87745 + * tree-vectorizer.h (get_earlier_stmt): Remove. + (get_later_stmt): Pick up UID from the original non-pattern stmt. + + 2018-10-24 Richard Biener + + PR tree-optimization/87665 + * tree-vect-data-refs.c (vect_preserves_scalar_order_p): Adjust + to reflect reality. + 2018-11-26 Richard Biener Backport from mainline diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b5a5d8654c1a..c260750ffe4d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,22 @@ +2018-11-26 Richard Biener + + Backport from mainline + 2018-10-15 Richard Biener + + PR middle-end/87610 + * gcc.dg/torture/restrict-6.c: New testcase. + + 2018-10-25 Richard Biener + + PR tree-optimization/87665 + PR tree-optimization/87745 + * gfortran.dg/20181025-1.f: New testcase. + + 2018-10-24 Richard Biener + + PR tree-optimization/87665 + * gcc.dg/torture/pr87665.c: New testcase. + 2018-11-26 Richard Biener Backport from mainline diff --git a/gcc/testsuite/gcc.dg/torture/pr87665.c b/gcc/testsuite/gcc.dg/torture/pr87665.c new file mode 100644 index 000000000000..6f5e968b6284 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr87665.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ + +struct X { long x; long y; }; + +struct X a[1024], b[1024]; + +void foo () +{ + for (int i = 0; i < 1024; ++i) + { + long tem = a[i].x; + a[i].x = 0; + b[i].x = tem; + b[i].y = a[i].y; + } +} + +int main() +{ + for (int i = 0; i < 1024; ++i) + a[i].x = i; + foo (); + for (int i = 0; i < 1024; ++i) + if (b[i].x != i) + __builtin_abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/restrict-6.c b/gcc/testsuite/gcc.dg/torture/restrict-6.c new file mode 100644 index 000000000000..9fe12a68850a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/restrict-6.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ + +extern void abort (void); + +void __attribute__((noinline)) g(int **a, int *b) +{ + *a = b; +} + +int foo(int * restrict p, int *q) +{ + g(&q, p); + *p = 1; + *q = 2; + return *p + *q; +} + +int main() +{ + int x, y; + if (foo(&x, &y) != 4) + abort (); + return 0; +} diff --git a/gcc/testsuite/gfortran.dg/20181025-1.f b/gcc/testsuite/gfortran.dg/20181025-1.f new file mode 100644 index 000000000000..1acbd72616cc --- /dev/null +++ b/gcc/testsuite/gfortran.dg/20181025-1.f @@ -0,0 +1,28 @@ +! { dg-do compile } +! { dg-options "-Ofast" } +! { dg-additional-options "-mavx2" { target { x86_64-*-* i?86-*-* } } } + SUBROUTINE FOO(EF3,CA,ZA,NATA,IC4,NFRGPT) + IMPLICIT DOUBLE PRECISION (A-H,O-Z) + PARAMETER (MXATM=500) + COMMON DE(3,MXATM) + DIMENSION CA(3,NATA) + DIMENSION ZA(NATA) + DIMENSION EF3(3,NFRGPT) + DO II = 1,NATA + XII = XJ - CA(1,II) + YII = YJ - CA(2,II) + ZII = ZJ - CA(3,II) + RJII = SQRT(XII*XII + YII*YII + ZII*ZII) + R3 = RJII*RJII*RJII + IF (IC4.EQ.0) THEN + DE(1,II) = DE(1,II) - S2*ZA(II)*XII/R3 + DE(2,II) = DE(2,II) - S2*ZA(II)*YII/R3 + DE(3,II) = DE(3,II) - S2*ZA(II)*ZII/R3 + ELSE + EF3(1,IC4+II) = EF3(1,IC4+II) - S2*ZA(II)*XII/R3 + EF3(2,IC4+II) = EF3(2,IC4+II) - S2*ZA(II)*YII/R3 + EF3(3,IC4+II) = EF3(3,IC4+II) - S2*ZA(II)*ZII/R3 + END IF + END DO + RETURN + END diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 33ad80efe3c4..b5a5f0f54d19 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -7274,6 +7274,7 @@ delete_points_to_sets (void) struct vls_data { unsigned short clique; + bool escaped_p; bitmap rvars; }; @@ -7285,6 +7286,7 @@ visit_loadstore (gimple *, tree base, tree ref, void *data) { unsigned short clique = ((vls_data *) data)->clique; bitmap rvars = ((vls_data *) data)->rvars; + bool escaped_p = ((vls_data *) data)->escaped_p; if (TREE_CODE (base) == MEM_REF || TREE_CODE (base) == TARGET_MEM_REF) { @@ -7305,7 +7307,8 @@ visit_loadstore (gimple *, tree base, tree ref, void *data) return false; vi = get_varinfo (find (vi->id)); - if (bitmap_intersect_p (rvars, vi->solution)) + if (bitmap_intersect_p (rvars, vi->solution) + || (escaped_p && bitmap_bit_p (vi->solution, escaped_id))) return false; } @@ -7382,6 +7385,7 @@ compute_dependence_clique (void) unsigned short clique = 0; unsigned short last_ruid = 0; bitmap rvars = BITMAP_ALLOC (NULL); + bool escaped_p = false; for (unsigned i = 0; i < num_ssa_names; ++i) { tree ptr = ssa_name (i); @@ -7451,7 +7455,12 @@ compute_dependence_clique (void) last_ruid); } if (used) - bitmap_set_bit (rvars, restrict_var->id); + { + bitmap_set_bit (rvars, restrict_var->id); + varinfo_t escaped = get_varinfo (find (escaped_id)); + if (bitmap_bit_p (escaped->solution, restrict_var->id)) + escaped_p = true; + } } } @@ -7464,7 +7473,7 @@ compute_dependence_clique (void) parameters) we can't restrict scoping properly thus the following is too aggressive there. For now we have excluded those globals from getting into the MR_DEPENDENCE machinery. */ - vls_data data = { clique, rvars }; + vls_data data = { clique, escaped_p, rvars }; basic_block bb; FOR_EACH_BB_FN (bb, cfun) for (gimple_stmt_iterator gsi = gsi_start_bb (bb); diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index f0e97060d7b8..9c32d9a90eec 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -195,6 +195,45 @@ vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo) } +/* Return true if we know that the order of vectorized STMT_A and + vectorized STMT_B will be the same as the order of STMT_A and STMT_B. + At least one of the statements is a write. */ + +static bool +vect_preserves_scalar_order_p (gimple *stmt_a, gimple *stmt_b) +{ + stmt_vec_info stmtinfo_a = vinfo_for_stmt (stmt_a); + stmt_vec_info stmtinfo_b = vinfo_for_stmt (stmt_b); + + /* Single statements are always kept in their original order. */ + if (!STMT_VINFO_GROUPED_ACCESS (stmtinfo_a) + && !STMT_VINFO_GROUPED_ACCESS (stmtinfo_b)) + return true; + + /* STMT_A and STMT_B belong to overlapping groups. All loads in a + group are emitted at the position of the last scalar load and all + stores in a group are emitted at the position of the last scalar store. + Compute that position and check whether the resulting order matches + the current one. */ + gimple *last_a = GROUP_FIRST_ELEMENT (stmtinfo_a); + if (last_a) + for (gimple *s = GROUP_NEXT_ELEMENT (vinfo_for_stmt (last_a)); s; + s = GROUP_NEXT_ELEMENT (vinfo_for_stmt (s))) + last_a = get_later_stmt (last_a, s); + else + last_a = stmt_a; + gimple *last_b = GROUP_FIRST_ELEMENT (stmtinfo_b); + if (last_b) + for (gimple *s = GROUP_NEXT_ELEMENT (vinfo_for_stmt (last_b)); s; + s = GROUP_NEXT_ELEMENT (vinfo_for_stmt (s))) + last_b = get_later_stmt (last_b, s); + else + last_b = stmt_b; + return ((get_later_stmt (last_a, last_b) == last_a) + == (get_later_stmt (stmt_a, stmt_b) == stmt_a)); +} + + /* Function vect_analyze_data_ref_dependence. Return TRUE if there (might) exist a dependence between a memory-reference @@ -378,20 +417,13 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, ... = a[i]; a[i+1] = ...; where loads from the group interleave with the store. */ - if (STMT_VINFO_GROUPED_ACCESS (stmtinfo_a) - || STMT_VINFO_GROUPED_ACCESS (stmtinfo_b)) + if (!vect_preserves_scalar_order_p (DR_STMT (dra), DR_STMT (drb))) { - gimple *earlier_stmt; - earlier_stmt = get_earlier_stmt (DR_STMT (dra), DR_STMT (drb)); - if (DR_IS_WRITE - (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt)))) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "READ_WRITE dependence in interleaving." - "\n"); - return true; - } + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "READ_WRITE dependence in interleaving." + "\n"); + return true; } unsigned int step_prec = TYPE_PRECISION (TREE_TYPE (DR_STEP (dra))); diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 12bb904abee5..276289bd8cf9 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -833,32 +833,22 @@ set_vinfo_for_stmt (gimple *stmt, stmt_vec_info info) } } -/* Return the earlier statement between STMT1 and STMT2. */ +/* Return TRUE if a statement represented by STMT_INFO is a part of a + pattern. */ -static inline gimple * -get_earlier_stmt (gimple *stmt1, gimple *stmt2) +static inline bool +is_pattern_stmt_p (stmt_vec_info stmt_info) { - unsigned int uid1, uid2; - - if (stmt1 == NULL) - return stmt2; - - if (stmt2 == NULL) - return stmt1; - - uid1 = gimple_uid (stmt1); - uid2 = gimple_uid (stmt2); - - if (uid1 == 0 || uid2 == 0) - return NULL; + gimple *related_stmt; + stmt_vec_info related_stmt_info; - gcc_checking_assert (uid1 <= stmt_vec_info_vec.length () - && uid2 <= stmt_vec_info_vec.length ()); + related_stmt = STMT_VINFO_RELATED_STMT (stmt_info); + if (related_stmt + && (related_stmt_info = vinfo_for_stmt (related_stmt)) + && STMT_VINFO_IN_PATTERN_P (related_stmt_info)) + return true; - if (uid1 < uid2) - return stmt1; - else - return stmt2; + return false; } /* Return the later statement between STMT1 and STMT2. */ @@ -874,8 +864,12 @@ get_later_stmt (gimple *stmt1, gimple *stmt2) if (stmt2 == NULL) return stmt1; - uid1 = gimple_uid (stmt1); - uid2 = gimple_uid (stmt2); + stmt_vec_info stmt_info1 = vinfo_for_stmt (stmt1); + stmt_vec_info stmt_info2 = vinfo_for_stmt (stmt2); + uid1 = gimple_uid (is_pattern_stmt_p (stmt_info1) + ? STMT_VINFO_RELATED_STMT (stmt_info1) : stmt1); + uid2 = gimple_uid (is_pattern_stmt_p (stmt_info2) + ? STMT_VINFO_RELATED_STMT (stmt_info2) : stmt2); if (uid1 == 0 || uid2 == 0) return NULL; @@ -889,24 +883,6 @@ get_later_stmt (gimple *stmt1, gimple *stmt2) return stmt2; } -/* Return TRUE if a statement represented by STMT_INFO is a part of a - pattern. */ - -static inline bool -is_pattern_stmt_p (stmt_vec_info stmt_info) -{ - gimple *related_stmt; - stmt_vec_info related_stmt_info; - - related_stmt = STMT_VINFO_RELATED_STMT (stmt_info); - if (related_stmt - && (related_stmt_info = vinfo_for_stmt (related_stmt)) - && STMT_VINFO_IN_PATTERN_P (related_stmt_info)) - return true; - - return false; -} - /* Return true if BB is a loop header. */ static inline bool