I've applied the following backports to gcc 8 (all approved earlier). Tested on aarch64-linux-gnu and x86_64-linux-gnu.
Richard
>From 7a2f576c3b40eca0a846553af5b1dfb05d84eb71 Mon Sep 17 00:00:00 2001 From: Richard Sandiford <richard.sandif...@arm.com> Date: Fri, 9 Aug 2019 09:37:55 +0000 Subject: [PATCH 1/5] Reject tail calls that read from an escaped RESULT_DECL [PR90313] In this PR we have two return paths from a function "map". The common code sets <result> to the value returned by one path, while the other path does: <retval> = map (&<retval>, ...); We treated this call as tail recursion, losing the copy semantics on the value returned by the recursive call. We'd correctly reject the same thing for variables: local = map (&local, ...); The problem is that RESULT_DECLs didn't get the same treatment. 2020-02-25 Richard Sandiford <richard.sandif...@arm.com> gcc/ Backport from mainline 2019-08-09 Richard Sandiford <richard.sandif...@arm.com> PR middle-end/90313 * tree-tailcall.c (find_tail_calls): Reject calls that might read from an escaped RESULT_DECL. gcc/testsuite/ PR middle-end/90313 * g++.dg/torture/pr90313.cc: New test. --- gcc/testsuite/g++.dg/torture/pr90313.cc | 33 +++++++++++++++++++++++++ gcc/tree-tailcall.c | 29 ++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 gcc/testsuite/g++.dg/torture/pr90313.cc diff --git a/gcc/testsuite/g++.dg/torture/pr90313.cc b/gcc/testsuite/g++.dg/torture/pr90313.cc new file mode 100644 index 00000000000..d9f183a2939 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr90313.cc @@ -0,0 +1,33 @@ +// { dg-do run } + +#include <stddef.h> + +namespace std { + template<typename T, size_t N> struct array { + T elems[N]; + const T &operator[](size_t i) const { return elems[i]; } + }; +} + +using Coordinates = std::array<double, 3>; + +Coordinates map(const Coordinates &c, size_t level) +{ + Coordinates result{ c[1], c[2], c[0] }; + + if (level != 0) + result = map (result, level - 1); + + return result; +} + +int main() +{ + Coordinates vecOfCoordinates = { 1.0, 2.0, 3.0 }; + + auto result = map(vecOfCoordinates, 1); + if (result[0] != 3 || result[1] != 1 || result[2] != 2) + __builtin_abort (); + + return 0; +} diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c index de18f9bcf87..aeca4e559c6 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -479,6 +479,35 @@ find_tail_calls (basic_block bb, struct tailcall **ret) && !stmt_can_throw_external (stmt)) return; + /* If the function returns a value, then at present, the tail call + must return the same type of value. There is conceptually a copy + between the object returned by the tail call candidate and the + object returned by CFUN itself. + + This means that if we have: + + lhs = f (&<retval>); // f reads from <retval> + // (lhs is usually also <retval>) + + there is a copy between the temporary object returned by f and lhs, + meaning that any use of <retval> in f occurs before the assignment + to lhs begins. Thus the <retval> that is live on entry to the call + to f is really an independent local variable V that happens to be + stored in the RESULT_DECL rather than a local VAR_DECL. + + Turning this into a tail call would remove the copy and make the + lifetimes of the return value and V overlap. The same applies to + tail recursion, since if f can read from <retval>, we have to assume + that CFUN might already have written to <retval> before the call. + + The problem doesn't apply when <retval> is passed by value, but that + isn't a case we handle anyway. */ + tree result_decl = DECL_RESULT (cfun->decl); + if (result_decl + && may_be_aliased (result_decl) + && ref_maybe_used_by_stmt_p (call, result_decl)) + return; + /* We found the call, check whether it is suitable. */ tail_recursion = false; func = gimple_call_fndecl (call); -- 2.17.1
>From 785eda9390473e42f0e0b7199c42032a0432de68 Mon Sep 17 00:00:00 2001 From: Richard Sandiford <richard.sandif...@arm.com> Date: Mon, 11 Nov 2019 19:43:52 +0000 Subject: [PATCH 2/5] Fix SLP downward group access classification [PR92420] This PR was caused by the SLP handling in get_group_load_store_type returning VMAT_CONTIGUOUS rather than VMAT_CONTIGUOUS_REVERSE for downward groups. A more elaborate fix would be to try to combine the reverse permutation into SLP_TREE_LOAD_PERMUTATION for loads, but that's really a follow-on optimisation and not backport material. It might also not necessarily be a win, if the target supports (say) reversing and odd/even swaps as independent permutes but doesn't recognise the combined form. 2020-02-25 Richard Sandiford <richard.sandif...@arm.com> gcc/ Backport from mainline 2019-11-11 Richard Sandiford <richard.sandif...@arm.com> PR tree-optimization/92420 * tree-vect-stmts.c (get_negative_load_store_type): Move further up file. (get_group_load_store_type): Use it for reversed SLP accesses. gcc/testsuite/ PR tree-optimization/92420 * gcc.dg/vect/pr92420.c: New test. --- gcc/testsuite/gcc.dg/vect/pr92420.c | 48 ++++++++++++ gcc/tree-vect-stmts.c | 112 +++++++++++++++------------- 2 files changed, 108 insertions(+), 52 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vect/pr92420.c diff --git a/gcc/testsuite/gcc.dg/vect/pr92420.c b/gcc/testsuite/gcc.dg/vect/pr92420.c new file mode 100644 index 00000000000..e43539fbbd7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr92420.c @@ -0,0 +1,48 @@ +/* { dg-additional-options "-mavx2" { target avx_runtime } } */ + +#include "tree-vect.h" + +#define N 16 +struct C { int r, i; }; +struct C a[N], b[N], c[N], d[N], e[N]; + +__attribute__((noipa)) static void +foo (struct C *__restrict x, struct C *__restrict y, struct C *__restrict z, int w) +{ + int i; + for (int i = 0; i < w; i++) + { + z[i].r = x[i].r * y[-1 - i].r - x[i].i * y[-1 - i].i; + z[i].i = x[i].i * y[-1 - i].r + x[i].r * y[-1 - i].i; + } +} + +__attribute__((noipa)) static void +bar (struct C *__restrict x, struct C *__restrict y, struct C *__restrict z, int w) +{ + int i; + for (int i = 0; i < w; i++) + { + z[i].r = x[i].r * y[i].r - x[i].i * y[i].i; + z[i].i = x[i].i * y[i].r + x[i].r * y[i].i; + } +} + +int +main () +{ + check_vect (); + int i; + for (i = 0; i < N; ++i) + { + a[i].r = N - i; a[i].i = i - N; + b[i].r = i - N; b[i].i = i + N; + c[i].r = -1 - i; c[i].i = 2 * N - 1 - i; + } + foo (a, b + N, d, N); + bar (a, c, e, N); + for (i = 0; i < N; ++i) + if (d[i].r != e[i].r || d[i].i != e[i].i) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index c3c16416e2e..7472558048c 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -2018,6 +2018,57 @@ perm_mask_for_reverse (tree vectype) return vect_gen_perm_mask_checked (vectype, indices); } +/* A subroutine of get_load_store_type, with a subset of the same + arguments. Handle the case where STMT is a load or store that + accesses consecutive elements with a negative step. */ + +static vect_memory_access_type +get_negative_load_store_type (gimple *stmt, tree vectype, + vec_load_store_type vls_type, + unsigned int ncopies) +{ + stmt_vec_info stmt_info = vinfo_for_stmt (stmt); + struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info); + dr_alignment_support alignment_support_scheme; + + if (ncopies > 1) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "multiple types with negative step.\n"); + return VMAT_ELEMENTWISE; + } + + alignment_support_scheme = vect_supportable_dr_alignment (dr, false); + if (alignment_support_scheme != dr_aligned + && alignment_support_scheme != dr_unaligned_supported) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "negative step but alignment required.\n"); + return VMAT_ELEMENTWISE; + } + + if (vls_type == VLS_STORE_INVARIANT) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, + "negative step with invariant source;" + " no permute needed.\n"); + return VMAT_CONTIGUOUS_DOWN; + } + + if (!perm_mask_for_reverse (vectype)) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "negative step and reversing not supported.\n"); + return VMAT_ELEMENTWISE; + } + + return VMAT_CONTIGUOUS_REVERSE; +} + /* STMT is either a masked or unconditional store. Return the value being stored. */ @@ -2121,7 +2172,15 @@ get_group_load_store_type (gimple *stmt, tree vectype, bool slp, "Peeling for outer loop is not supported\n"); return false; } - *memory_access_type = VMAT_CONTIGUOUS; + int cmp = compare_step_with_zero (stmt); + if (cmp < 0) + *memory_access_type = get_negative_load_store_type + (stmt, vectype, vls_type, 1); + else + { + gcc_assert (!loop_vinfo || cmp > 0); + *memory_access_type = VMAT_CONTIGUOUS; + } } } else @@ -2224,57 +2283,6 @@ get_group_load_store_type (gimple *stmt, tree vectype, bool slp, return true; } -/* A subroutine of get_load_store_type, with a subset of the same - arguments. Handle the case where STMT is a load or store that - accesses consecutive elements with a negative step. */ - -static vect_memory_access_type -get_negative_load_store_type (gimple *stmt, tree vectype, - vec_load_store_type vls_type, - unsigned int ncopies) -{ - stmt_vec_info stmt_info = vinfo_for_stmt (stmt); - struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info); - dr_alignment_support alignment_support_scheme; - - if (ncopies > 1) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "multiple types with negative step.\n"); - return VMAT_ELEMENTWISE; - } - - alignment_support_scheme = vect_supportable_dr_alignment (dr, false); - if (alignment_support_scheme != dr_aligned - && alignment_support_scheme != dr_unaligned_supported) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "negative step but alignment required.\n"); - return VMAT_ELEMENTWISE; - } - - if (vls_type == VLS_STORE_INVARIANT) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "negative step with invariant source;" - " no permute needed.\n"); - return VMAT_CONTIGUOUS_DOWN; - } - - if (!perm_mask_for_reverse (vectype)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "negative step and reversing not supported.\n"); - return VMAT_ELEMENTWISE; - } - - return VMAT_CONTIGUOUS_REVERSE; -} - /* Analyze load or store statement STMT of type VLS_TYPE. Return true if there is a memory access type that the vectorized form can use, storing it in *MEMORY_ACCESS_TYPE if so. If we decide to use gathers -- 2.17.1
>From e4efe90aec0a5f722341c1070680d2ab3a438a7d Mon Sep 17 00:00:00 2001 From: Richard Sandiford <richard.sandif...@arm.com> Date: Thu, 5 Dec 2019 14:20:38 +0000 Subject: [PATCH 3/5] Check for bitwise identity when encoding VECTOR_CSTs [PR92768] This PR shows that we weren't checking for bitwise-identical values when trying to encode a VECTOR_CST, so -0.0 was treated the same as 0.0 for -fno-signed-zeros. The patch adds a new OEP flag to select that behaviour. 2020-02-25 Richard Sandiford <richard.sandif...@arm.com> gcc/ Backport from mainline 2019-12-05 Richard Sandiford <richard.sandif...@arm.com> PR middle-end/92768 * tree-core.h (OEP_BITWISE): New flag. * fold-const.c (operand_compare::operand_equal_p): Handle it. * tree-vector-builder.h (tree_vector_builder::equal_p): Pass it. gcc/testsuite/ PR middle-end/92768 * gcc.dg/pr92768.c: New test. --- gcc/fold-const.c | 17 ++++++++++++++--- gcc/testsuite/gcc.dg/pr92768.c | 7 +++++++ gcc/tree-core.h | 3 ++- gcc/tree-vector-builder.h | 2 +- 4 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr92768.c diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c64c4b10f8d..9183c3752ce 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -2894,6 +2894,11 @@ combine_comparisons (location_t loc, If OEP_LEXICOGRAPHIC is set, then also handle expressions with side-effects such as MODIFY_EXPR, RETURN_EXPR, as well as STATEMENT_LISTs. + If OEP_BITWISE is set, then require the values to be bitwise identical + rather than simply numerically equal. Do not take advantage of things + like math-related flags or undefined behavior; only return true for + values that are provably bitwise identical in all circumstances. + Unless OEP_MATCH_SIDE_EFFECTS is set, the function returns false on any operand with side effect. This is unnecesarily conservative in the case we know that arg0 and arg1 are in disjoint code paths (such as in @@ -2937,6 +2942,11 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) if (!TREE_TYPE (arg0) || !TREE_TYPE (arg1)) return 0; + /* Bitwise identity makes no sense if the values have different layouts. */ + if ((flags & OEP_BITWISE) + && !tree_nop_conversion_p (TREE_TYPE (arg0), TREE_TYPE (arg1))) + return 0; + /* We cannot consider pointers to different address space equal. */ if (POINTER_TYPE_P (TREE_TYPE (arg0)) && POINTER_TYPE_P (TREE_TYPE (arg1)) @@ -3069,8 +3079,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) if (real_identical (&TREE_REAL_CST (arg0), &TREE_REAL_CST (arg1))) return 1; - - if (!HONOR_SIGNED_ZEROS (arg0)) + if (!(flags & OEP_BITWISE) && !HONOR_SIGNED_ZEROS (arg0)) { /* If we do not distinguish between signed and unsigned zero, consider them equal. */ @@ -3122,7 +3131,9 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) break; } - if (flags & OEP_ONLY_CONST) + /* Don't handle more cases for OEP_BITWISE, since we can't guarantee that + two instances of undefined behavior will give identical results. */ + if (flags & (OEP_ONLY_CONST | OEP_BITWISE)) return 0; /* Define macros to test an operand from arg0 and arg1 for equality and a diff --git a/gcc/testsuite/gcc.dg/pr92768.c b/gcc/testsuite/gcc.dg/pr92768.c new file mode 100644 index 00000000000..e2a3f9ccacc --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr92768.c @@ -0,0 +1,7 @@ +/* PR tree-optimization/92768 */ +/* { dg-options "-O2 -fno-signed-zeros -fdump-tree-optimized -w -Wno-psabi" } */ + +typedef float v4sf __attribute__((vector_size(16))); +v4sf f () { return (v4sf) { 0.0, -0.0, 0.0, -0.0 }; } + +/* { dg-final { scan-tree-dump {{ 0\.0, -0\.0, 0\.0, -0\.0 }} "optimized" } } */ diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 4f72861ad64..198586bb7f9 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -819,7 +819,8 @@ enum operand_equal_flag { /* Internal within inchash::add_expr: */ OEP_HASH_CHECK = 32, /* Makes operand_equal_p handle more expressions: */ - OEP_LEXICOGRAPHIC = 64 + OEP_LEXICOGRAPHIC = 64, + OEP_BITWISE = 128 }; /* Enum and arrays used for tree allocation stats. diff --git a/gcc/tree-vector-builder.h b/gcc/tree-vector-builder.h index 6a248a64254..fb7941ba602 100644 --- a/gcc/tree-vector-builder.h +++ b/gcc/tree-vector-builder.h @@ -82,7 +82,7 @@ tree_vector_builder::new_vector (tree type, unsigned int npatterns, inline bool tree_vector_builder::equal_p (const_tree elt1, const_tree elt2) const { - return operand_equal_p (elt1, elt2, 0); + return operand_equal_p (elt1, elt2, OEP_BITWISE); } /* Return true if a stepped representation is OK. We don't allow -- 2.17.1
>From 50c7f76eb30041a9b219cd6535c8c09583cc052b Mon Sep 17 00:00:00 2001 From: Richard Sandiford <richard.sandif...@arm.com> Date: Mon, 27 Jan 2020 19:37:55 +0000 Subject: [PATCH 4/5] predcom: Fix invalid store-store commoning [PR93434] predcom has the following code to stop one rogue load from interfering with other store-load opportunities: /* If A is read and B write or vice versa and there is unsuitable dependence, instead of merging both components into a component that will certainly not pass suitable_component_p, just put the read into bad component, perhaps at least the write together with all the other data refs in it's component will be optimizable. */ But when store-store commoning was added later, this had the effect of ignoring loads that occur between two candidate stores. There is code further up to handle loads and stores with unknown dependences: /* Don't do store elimination if there is any unknown dependence for any store data reference. */ if ((DR_IS_WRITE (dra) || DR_IS_WRITE (drb)) && (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know || DDR_NUM_DIST_VECTS (ddr) == 0)) eliminate_store_p = false; But the store-load code above skips loads for *known* dependences if (a) the load has already been marked "bad" or (b) the data-ref machinery knows the dependence distance, but determine_offsets can't handle the combination. (a) happens to be the problem in the testcase, but a different sequence could have given (b) instead. We have writes to individual fields of a structure and reads from the whole structure. Since determine_offsets requires the types to be the same, it returns false for each such read/write combination. This patch records which components have had loads removed and prevents store-store commoning for them. It's a bit too pessimistic, since there shouldn't be a problem if a "bad" load dominates all stores in a component. But (a) we can't AFAIK use pcom_stmt_dominates_stmt_p here and (b) the handling for that case would probably need to be removed again if we handled more exotic cases in future. 2020-02-25 Richard Sandiford <richard.sandif...@arm.com> gcc/ Backport from mainline 2020-01-28 Richard Sandiford <richard.sandif...@arm.com> PR tree-optimization/93434 * tree-predcom.c (split_data_refs_to_components): Record which components have had aliasing loads removed. Prevent store-store commoning for all such components. gcc/testsuite/ PR tree-optimization/93434 * gcc.c-torture/execute/pr93434.c: New test. --- gcc/testsuite/gcc.c-torture/execute/pr93434.c | 36 +++++++++++++++++++ gcc/tree-predcom.c | 24 +++++++++++-- 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr93434.c diff --git a/gcc/testsuite/gcc.c-torture/execute/pr93434.c b/gcc/testsuite/gcc.c-torture/execute/pr93434.c new file mode 100644 index 00000000000..e786252794b --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr93434.c @@ -0,0 +1,36 @@ +typedef struct creal_T { + double re; + double im; +} creal_T; + +#define N 16 +int main() { + int k; + int i; + int j; + creal_T t2[N]; + double inval; + + inval = 1.0; + for (j = 0; j < N; ++j) { + t2[j].re = 0; + t2[j].im = 0; + } + + for (j = 0; j < N/4; j++) { + i = j * 4; + t2[i].re = inval; + t2[i].im = inval; + k = i + 3; + t2[k].re = inval; + t2[k].im = inval; + t2[i] = t2[k]; + t2[k].re = inval; + } + + for (i = 0; i < 2; ++i) + if (t2[i].re != !i || t2[i].im != !i) + __builtin_abort (); + + return 0; +} diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c index c4c7613293d..fd3f2202f6b 100644 --- a/gcc/tree-predcom.c +++ b/gcc/tree-predcom.c @@ -767,6 +767,7 @@ split_data_refs_to_components (struct loop *loop, /* Don't do store elimination if loop has multiple exit edges. */ bool eliminate_store_p = single_exit (loop) != NULL; basic_block last_always_executed = last_always_executed_block (loop); + auto_bitmap no_store_store_comps; FOR_EACH_VEC_ELT (datarefs, i, dr) { @@ -838,9 +839,13 @@ split_data_refs_to_components (struct loop *loop, else if (DR_IS_READ (dra) && ib != bad) { if (ia == bad) - continue; + { + bitmap_set_bit (no_store_store_comps, ib); + continue; + } else if (!determine_offset (dra, drb, &dummy_off)) { + bitmap_set_bit (no_store_store_comps, ib); merge_comps (comp_father, comp_size, bad, ia); continue; } @@ -848,9 +853,13 @@ split_data_refs_to_components (struct loop *loop, else if (DR_IS_READ (drb) && ia != bad) { if (ib == bad) - continue; + { + bitmap_set_bit (no_store_store_comps, ia); + continue; + } else if (!determine_offset (dra, drb, &dummy_off)) { + bitmap_set_bit (no_store_store_comps, ia); merge_comps (comp_father, comp_size, bad, ib); continue; } @@ -908,6 +917,17 @@ split_data_refs_to_components (struct loop *loop, comp->refs.quick_push (dataref); } + if (eliminate_store_p) + { + bitmap_iterator bi; + EXECUTE_IF_SET_IN_BITMAP (no_store_store_comps, 0, ia, bi) + { + ca = component_of (comp_father, ia); + if (ca != bad) + comps[ca]->eliminate_store_p = false; + } + } + for (i = 0; i < n; i++) { comp = comps[i]; -- 2.17.1
>From a6378029183005ff05865496975ff706d91853d8 Mon Sep 17 00:00:00 2001 From: Richard Sandiford <richard.sandif...@arm.com> Date: Tue, 18 Feb 2020 18:06:32 +0000 Subject: [PATCH 5/5] vect: Fix offset calculation for -ve strides [PR93767] This PR is a regression caused by r256644, which added support for alias checks involving variable strides. One of the changes in that commit was to split the access size out of the segment length. The PR shows that I hadn't done that correctly for the handling of negative strides in vect_compile_time_alias. The old code was: const_length_a = (-wi::to_poly_wide (segment_length_a)).force_uhwi (); offset_a = (offset_a + vect_get_scalar_dr_size (a)) - const_length_a; where vect_get_scalar_dr_size (a) was cancelling out the subtraction of the access size inherent in "- const_length_a". Taking the access size out of the segment length meant that the addition was no longer needed/correct. 2020-02-25 Richard Sandiford <richard.sandif...@arm.com> gcc/ Backport from mainline 2020-02-19 Richard Sandiford <richard.sandif...@arm.com> PR tree-optimization/93767 * tree-vect-data-refs.c (vect_compile_time_alias): Remove the access-size bias from the offset calculations for negative strides. gcc/testsuite/ Backport from mainline 2020-02-19 Richard Sandiford <richard.sandif...@arm.com> PR tree-optimization/93767 * gcc.dg/vect/pr93767.c: New test. --- gcc/testsuite/gcc.dg/vect/pr93767.c | 13 +++++++++++++ gcc/tree-vect-data-refs.c | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vect/pr93767.c diff --git a/gcc/testsuite/gcc.dg/vect/pr93767.c b/gcc/testsuite/gcc.dg/vect/pr93767.c new file mode 100644 index 00000000000..5f95d7bd35b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr93767.c @@ -0,0 +1,13 @@ +int +main () +{ + int a[10], b; + for (b = 6; b >= 3; b--) + { + a[b] = 1; + a[b + 2] = a[3]; + } + if (a[5] != 1) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index b7a82986a45..81c86d73b26 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -3245,14 +3245,14 @@ vect_compile_time_alias (struct data_reference *a, struct data_reference *b, if (tree_int_cst_compare (DR_STEP (a), size_zero_node) < 0) { const_length_a = (-wi::to_poly_wide (segment_length_a)).force_uhwi (); - offset_a = (offset_a + access_size_a) - const_length_a; + offset_a -= const_length_a; } else const_length_a = tree_to_poly_uint64 (segment_length_a); if (tree_int_cst_compare (DR_STEP (b), size_zero_node) < 0) { const_length_b = (-wi::to_poly_wide (segment_length_b)).force_uhwi (); - offset_b = (offset_b + access_size_b) - const_length_b; + offset_b -= const_length_b; } else const_length_b = tree_to_poly_uint64 (segment_length_b); -- 2.17.1