This fixes wrong answer from data-dependence analysis by realizing that _all_ (even non-evolving) indirect accesses cannot be constrained to a full object size. This also gets rid of that ugly DR_UNCONSTRAINED_BASE hack (but effectively make it always active).
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2014-08-14 Richard Biener <rguent...@suse.de> PR tree-optimization/62031 * tree-data-ref.c (dr_analyze_indices): Do not set DR_UNCONSTRAINED_BASE. (dr_may_alias_p): All indirect accesses have to go the formerly DR_UNCONSTRAINED_BASE path. * tree-data-ref.h (struct indices): Remove unconstrained_base member. (DR_UNCONSTRAINED_BASE): Remove. * gcc.dg/torture/pr62031.c: New testcase. Index: gcc/tree-data-ref.c =================================================================== --- gcc/tree-data-ref.c (revision 213958) +++ gcc/tree-data-ref.c (working copy) @@ -982,7 +982,6 @@ dr_analyze_indices (struct data_referenc ref = fold_build2_loc (EXPR_LOCATION (ref), MEM_REF, TREE_TYPE (ref), base, memoff); - DR_UNCONSTRAINED_BASE (dr) = true; access_fns.safe_push (access_fn); } } @@ -1389,14 +1388,20 @@ dr_may_alias_p (const struct data_refere return false; } - /* If we had an evolution in a MEM_REF BASE_OBJECT we do not know - the size of the base-object. So we cannot do any offset/overlap - based analysis but have to rely on points-to information only. */ + /* If we had an evolution in a pointer-based MEM_REF BASE_OBJECT we + do not know the size of the base-object. So we cannot do any + offset/overlap based analysis but have to rely on points-to + information only. */ if (TREE_CODE (addr_a) == MEM_REF - && DR_UNCONSTRAINED_BASE (a)) + && TREE_CODE (TREE_OPERAND (addr_a, 0)) == SSA_NAME) { - if (TREE_CODE (addr_b) == MEM_REF - && DR_UNCONSTRAINED_BASE (b)) + /* For true dependences we can apply TBAA. */ + if (flag_strict_aliasing + && DR_IS_WRITE (a) && DR_IS_READ (b) + && !alias_sets_conflict_p (get_alias_set (DR_REF (a)), + get_alias_set (DR_REF (b)))) + return false; + if (TREE_CODE (addr_b) == MEM_REF) return ptr_derefs_may_alias_p (TREE_OPERAND (addr_a, 0), TREE_OPERAND (addr_b, 0)); else @@ -1404,9 +1409,21 @@ dr_may_alias_p (const struct data_refere build_fold_addr_expr (addr_b)); } else if (TREE_CODE (addr_b) == MEM_REF - && DR_UNCONSTRAINED_BASE (b)) - return ptr_derefs_may_alias_p (build_fold_addr_expr (addr_a), - TREE_OPERAND (addr_b, 0)); + && TREE_CODE (TREE_OPERAND (addr_b, 0)) == SSA_NAME) + { + /* For true dependences we can apply TBAA. */ + if (flag_strict_aliasing + && DR_IS_WRITE (a) && DR_IS_READ (b) + && !alias_sets_conflict_p (get_alias_set (DR_REF (a)), + get_alias_set (DR_REF (b)))) + return false; + if (TREE_CODE (addr_a) == MEM_REF) + return ptr_derefs_may_alias_p (TREE_OPERAND (addr_a, 0), + TREE_OPERAND (addr_b, 0)); + else + return ptr_derefs_may_alias_p (build_fold_addr_expr (addr_a), + TREE_OPERAND (addr_b, 0)); + } /* Otherwise DR_BASE_OBJECT is an access that covers the whole object that is being subsetted in the loop nest. */ Index: gcc/tree-data-ref.h =================================================================== --- gcc/tree-data-ref.h (revision 213958) +++ gcc/tree-data-ref.h (working copy) @@ -81,10 +81,6 @@ struct indices /* A list of chrecs. Access functions of the indices. */ vec<tree> access_fns; - - /* Whether BASE_OBJECT is an access representing the whole object - or whether the access could not be constrained. */ - bool unconstrained_base; }; struct dr_alias @@ -195,7 +191,6 @@ struct data_reference #define DR_STMT(DR) (DR)->stmt #define DR_REF(DR) (DR)->ref #define DR_BASE_OBJECT(DR) (DR)->indices.base_object -#define DR_UNCONSTRAINED_BASE(DR) (DR)->indices.unconstrained_base #define DR_ACCESS_FNS(DR) (DR)->indices.access_fns #define DR_ACCESS_FN(DR, I) DR_ACCESS_FNS (DR)[I] #define DR_NUM_DIMENSIONS(DR) DR_ACCESS_FNS (DR).length () Index: gcc/testsuite/gcc.dg/torture/pr62031.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr62031.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr62031.c (working copy) @@ -0,0 +1,52 @@ +/* { dg-do run } */ + +#include <stdlib.h> + +#define NUM_OF_STATES 4 +typedef unsigned int entry_t[2]; +typedef struct entries_item { entry_t metricEntries_[0]; } entries_item_t; + +void __attribute__((noinline,noclone)) +test_00(size_t numOfStates, entries_item_t* p_bm, + const unsigned int* polyArray, + size_t polyArraySize) +{ + size_t idx; + unsigned int hlp0, hlp1; + for (idx = 0; idx < numOfStates; ++idx) + { + size_t idy; + + hlp0 = (idx << 1) | 0x00; + hlp1 = (idx << 1) | 0x01; + p_bm->metricEntries_[idx][0] = 0; + p_bm->metricEntries_[idx][1] = 0; + for (idy = 0; idy < polyArraySize; ++idy) + { + p_bm->metricEntries_[idx][0] + |= __builtin_parity(hlp0 & polyArray[idy]) << idy; + p_bm->metricEntries_[idx][1] + |= __builtin_parity(hlp1 & polyArray[idy]) << idy; + } + } +} + +int main() +{ + unsigned int polyArray[] = { 0x07, 0x05 }; + entries_item_t* pBranchMetrics; + pBranchMetrics = malloc(sizeof(entry_t) * NUM_OF_STATES); + test_00(NUM_OF_STATES, pBranchMetrics, polyArray, + sizeof(polyArray) / sizeof(polyArray[0])); + if (pBranchMetrics->metricEntries_[0][0] != 0 + || pBranchMetrics->metricEntries_[0][1] != 3 + || pBranchMetrics->metricEntries_[1][0] != 1 + || pBranchMetrics->metricEntries_[1][1] != 2 + || pBranchMetrics->metricEntries_[2][0] != 3 + || pBranchMetrics->metricEntries_[2][1] != 0 + || pBranchMetrics->metricEntries_[3][0] != 2 + || pBranchMetrics->metricEntries_[3][1] != 1) + abort (); + free(pBranchMetrics); + return 0; +}