This concludes the series to try to fixup data-dependence analysis. The code is still "wrong", but it appears that the following split out patch cures the testcases I have and does not degenerate any in the testsuite. The patch also makes sense - we analyze the MEM_REF base pointer for its evolution to cover the cases of (mixed array and) pointer accesses like (*p)[i] when p accesses into the 2st dimension of a two-dimensional array. But it is not a good idea to claim that, if there is no evolution of p in the analyzed nest, the MEM_REF offset (whether it is zero or not) is the index of an independent dimension and can be used for disambiguation by data dependence analysis. What we also did is for not analyzable p's, put scev_not_known as the base of the MEM_REF and pass that to the oracle(s) via dr_may_alias_p. Something that leads to very funny disambiguations. Thus this patch restricts us to handling POLYNOMIAL_CHRECs.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. I'll try to forget about data-dependence analysis again now, given it kept me busy for three days :/ Richard. 2011-08-24 Richard Guenther <rguent...@suse.de> PR tree-optimization/50067 * tree-data-ref.c (dr_analyze_indices): Do not add an access function for a MEM_REF base that has no evolution in the loop nest or that is not analyzable. * gcc.dg/torture/pr50067-3.c: New testcase. * gcc.dg/torture/pr50067-4.c: Likewise. * gcc.dg/torture/pr50067-5.c: Likewise. Index: gcc/tree-data-ref.c =================================================================== *** gcc/tree-data-ref.c.orig 2011-08-24 11:43:10.000000000 +0200 --- gcc/tree-data-ref.c 2011-08-24 12:05:24.000000000 +0200 *************** dr_analyze_indices (struct data_referenc *** 881,905 **** aref = TREE_OPERAND (aref, 0); } if (TREE_CODE (aref) == MEM_REF) { op = TREE_OPERAND (aref, 0); access_fn = analyze_scalar_evolution (loop, op); access_fn = instantiate_scev (before_loop, loop, access_fn); ! base = initial_condition (access_fn); ! split_constant_offset (base, &base, &off); ! if (!integer_zerop (TREE_OPERAND (aref, 1))) { ! off = size_binop (PLUS_EXPR, off, ! fold_convert (ssizetype, TREE_OPERAND (aref, 1))); ! TREE_OPERAND (aref, 1) ! = build_int_cst (TREE_TYPE (TREE_OPERAND (aref, 1)), 0); } - access_fn = chrec_replace_initial_condition (access_fn, - fold_convert (TREE_TYPE (base), off)); - - TREE_OPERAND (aref, 0) = base; - VEC_safe_push (tree, heap, access_fns, access_fn); } if (TREE_CODE (ref) == MEM_REF --- 881,912 ---- aref = TREE_OPERAND (aref, 0); } + /* If the address operand of a MEM_REF base has an evolution in the + analyzed nest, add it as an additional independent access-function. */ if (TREE_CODE (aref) == MEM_REF) { op = TREE_OPERAND (aref, 0); access_fn = analyze_scalar_evolution (loop, op); access_fn = instantiate_scev (before_loop, loop, access_fn); ! if (TREE_CODE (access_fn) == POLYNOMIAL_CHREC) { ! base = initial_condition (access_fn); ! split_constant_offset (base, &base, &off); ! /* Fold the MEM_REF offset into the evolutions initial ! value to make more bases comparable. */ ! if (!integer_zerop (TREE_OPERAND (aref, 1))) ! { ! off = size_binop (PLUS_EXPR, off, ! fold_convert (ssizetype, ! TREE_OPERAND (aref, 1))); ! TREE_OPERAND (aref, 1) ! = build_int_cst (TREE_TYPE (TREE_OPERAND (aref, 1)), 0); ! } ! access_fn = chrec_replace_initial_condition ! (access_fn, fold_convert (TREE_TYPE (base), off)); ! TREE_OPERAND (aref, 0) = base; ! VEC_safe_push (tree, heap, access_fns, access_fn); } } if (TREE_CODE (ref) == MEM_REF Index: gcc/testsuite/gcc.dg/torture/pr50067-3.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/torture/pr50067-3.c 2011-08-24 11:50:43.000000000 +0200 *************** *** 0 **** --- 1,20 ---- + /* { dg-do run } */ + /* { dg-options "-fpredictive-commoning" } */ + + extern void abort (void); + int a[6] = { 0, 0, 0, 0, 7, 0 }; + static int *p = &a[4]; + + int + main () + { + int i; + for (i = 0; i < 4; ++i) + { + a[i + 1] = a[i + 2] > i; + *p &= ~1; + } + if (a[4] != 0) + abort (); + return 0; + } Index: gcc/testsuite/gcc.dg/torture/pr50067-4.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/torture/pr50067-4.c 2011-08-24 11:50:43.000000000 +0200 *************** *** 0 **** --- 1,25 ---- + /* { dg-do run } */ + + /* Verify we do not get a bogus access function with 0B vs. 1B which + disambiguates both accesses and leads to vectorization. */ + + extern int memcmp(const void *, const void *, __SIZE_TYPE__); + extern void abort (void); + short a[33] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; + short b[33] = { 0, }; + int main() + { + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + int i; + if (sizeof (short) == 2) + { + for (i = 0; i < 64; ++i) + { + (*((char(*)[])&a[1]))[i] = (*((char(*)[])&a[0]))[i+1]; + } + if (memcmp (&a, &b, sizeof (a)) != 0) + abort (); + } + #endif + return 0; + } Index: gcc/testsuite/gcc.dg/torture/pr50067-5.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/torture/pr50067-5.c 2011-08-24 11:50:43.000000000 +0200 *************** *** 0 **** --- 1,28 ---- + /* { dg-do run } */ + + /* Verify we do not get a bogus access function pairs with + exchanged dimensions, 0, {1, +, 1}_1 vs. {2B, +, 1}_1, 0 which + disambiguates both accesses and leads to vectorization. */ + + extern int memcmp(const void *, const void *, __SIZE_TYPE__); + extern void abort (void); + short a[33] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; + short b[33] = { 0, }; + char * volatile ap_ = (char *)&a[0]; + int main() + { + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + int i; + char *ap = ap_; + if (sizeof (short) == 2) + { + for (i = 0; i < 64; ++i) + { + (*((char(*)[])&ap[i+2]))[0] = (*((char(*)[])&ap[0]))[i+1]; + } + if (memcmp (&a, &b, sizeof (a)) != 0) + abort (); + } + #endif + return 0; + }