This fixes PR50838. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard. 2011-10-24 Richard Guenther <rguent...@suse.de> PR tree-optimization/50838 * tree-data-ref.c (dr_analyze_indices): Properly canonicalize a MEM_REF base if we change it. * gcc.dg/torture/pr50838.c: New testcase. Index: gcc/tree-data-ref.c =================================================================== *** gcc/tree-data-ref.c (revision 180374) --- gcc/tree-data-ref.c (working copy) *************** static void *** 855,861 **** dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) { VEC (tree, heap) *access_fns = NULL; ! tree ref, aref, op; tree base, off, access_fn; basic_block before_loop; --- 855,861 ---- dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) { VEC (tree, heap) *access_fns = NULL; ! tree ref, *aref, op; tree base, off, access_fn; basic_block before_loop; *************** dr_analyze_indices (struct data_referenc *** 886,935 **** } /* Analyze access functions of dimensions we know to be independent. */ ! aref = ref; ! while (handled_component_p (aref)) { ! if (TREE_CODE (aref) == ARRAY_REF) { ! op = TREE_OPERAND (aref, 1); access_fn = analyze_scalar_evolution (loop, op); access_fn = instantiate_scev (before_loop, loop, access_fn); VEC_safe_push (tree, heap, access_fns, access_fn); /* For ARRAY_REFs the base is the reference with the index replaced by zero if we can not strip it as the outermost component. */ ! if (aref == ref) ! ref = TREE_OPERAND (ref, 0); else ! TREE_OPERAND (aref, 1) = build_int_cst (TREE_TYPE (op), 0); } ! 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); } } --- 886,943 ---- } /* Analyze access functions of dimensions we know to be independent. */ ! aref = &ref; ! while (handled_component_p (*aref)) { ! if (TREE_CODE (*aref) == ARRAY_REF) { ! op = TREE_OPERAND (*aref, 1); access_fn = analyze_scalar_evolution (loop, op); access_fn = instantiate_scev (before_loop, loop, access_fn); VEC_safe_push (tree, heap, access_fns, access_fn); /* For ARRAY_REFs the base is the reference with the index replaced by zero if we can not strip it as the outermost component. */ ! if (*aref == ref) ! { ! *aref = TREE_OPERAND (*aref, 0); ! continue; ! } else ! TREE_OPERAND (*aref, 1) = build_int_cst (TREE_TYPE (op), 0); } ! 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) { + tree orig_type; base = initial_condition (access_fn); + orig_type = TREE_TYPE (base); + STRIP_USELESS_TYPE_CONVERSION (base); 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 (orig_type, off)); ! *aref = fold_build2_loc (EXPR_LOCATION (*aref), ! MEM_REF, TREE_TYPE (*aref), ! base, TREE_OPERAND (*aref, 1)); VEC_safe_push (tree, heap, access_fns, access_fn); } } Index: gcc/testsuite/gcc.dg/torture/pr50838.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr50838.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr50838.c (revision 0) *************** *** 0 **** --- 1,27 ---- + /* { dg-do compile } */ + + typedef void * gcv_object_t; + typedef gcv_object_t object; + typedef const void * Pseudofun; + extern struct pseudocode_tab_ { + Pseudofun pseudo_eql; + Pseudofun pseudo_iconv_wcslen; + Pseudofun pseudo_iconv_wcstombs; + Pseudofun pseudo_iconv_range; + } + pseudocode_tab; + extern struct symbol_tab_ { + object pointer[1024]; + } pseudofun_tab; + int + init_memory (void) + { + object* ptr2 = &pseudofun_tab.pointer[0]; + const Pseudofun* ptr1 = (const Pseudofun*)&pseudocode_tab; + unsigned int count = (sizeof(pseudocode_tab)/sizeof(Pseudofun)); + while (count--) + { + *ptr2++ = (gcv_object_t)(((unsigned char *)((*ptr1)))); + ptr1++; + } + }