https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80815
Bug ID: 80815 Summary: wrong code because of broken runtime alias check in vectorizer Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: amker at gcc dot gnu.org Target Milestone: --- Hi, I was suspecting that vect_prune_runtime_alias_check_list is broken, now I can create a test case for it: #include <stdio.h> int arr[2048]; int foo (int *a, int *b) { int i; int *a1 = a; int *a0 = a1 - 512; for (i = 0; i < 500; i++) { *b = *a0 + *a1; b++; a0--; a1--; } return 0; } int main (void) { int *a = &arr[1027]; int *b = &arr[1024]; int i; for (i = 0; i < 2048; i++) arr[i] = i; foo (a, b); for (i = 0; i < 2048; i++) fprintf (stdout, "%d: %d\n", i, arr[i]); return 0; } Compiled on x86_64 with below two commands: Binary 1) $ ../gcc -O2 -fno-inline ../x.c -o x.exe $ ./x.exe >/tmp/x Binary 2) ../gcc -Ofast -fno-inline ../x.c -o y.exe $ ./y.exe >/tmp/y We have: $ diff /tmp/x /tmp/y 1027,1028c1027,1028 < 1026: 2053 < 1027: 2054 --- > 1026: 1538 > 1027: 1536 I think the root cause is in below code: /* Generally the new segment length is the maximum of the left segment size and the right segment size plus the distance. ??? We can also build tree MAX_EXPR here but it's not clear this is profitable. */ else if (tree_fits_uhwi_p (dr_a1->seg_len) && tree_fits_uhwi_p (dr_a2->seg_len)) { unsigned HOST_WIDE_INT seg_len_a1 = tree_to_uhwi (dr_a1->seg_len); unsigned HOST_WIDE_INT seg_len_a2 = tree_to_uhwi (dr_a2->seg_len); dr_a1->seg_len = size_int (MAX (seg_len_a1, diff + seg_len_a2)); do_remove = true; } Here dr_a1 is *a0, dr_a2 is *a1 and dr_b1/dr_b2 is *b, and their ranges is like --------------------------------------------------------------> a0_en a0 a1_end b a1 b_end It should merge range_a0/range_a1 and result in range of a1, but because: 1) seg_len_a1 wraps to a large unsigned integer; 2) seg_len_a2 wraps to a large unsigned integer; 3) diff + seg_len_a2 wraps again to a small unsigned integer; The program falsely merges ranges to range_a0. As a result, loop is vectorized because range_a0 and range_b are considered not alias to each other. This is wrong because *a1 and *b overlaps at the first several iterations and have circle in dependence.