tree-affine is a bit overzealous when converting elements of pointer-typed combinations to sizetype. From IVOPTs we often get a combination that doesn't start with a pointer element in which case the result was a pure sizetype compute. This shows when fixing PR57511 in gcc.dg/tree-ssa/reassoc-19.c where we after the fix detect induction variables but manage to break the pattern we expect.
So the following re-arranges add_elt_to_tree to preserve pointerness when possible. Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2013-09-02 Richard Biener <rguent...@suse.de> * tree-affine.c (add_elt_to_tree): Avoid converting all pointer arithmetic to sizetype. * gcc.dg/tree-ssa/loop-4.c: Adjust scan looking for one memory reference. Index: gcc/tree-affine.c =================================================================== *** gcc/tree-affine.c (revision 202097) --- gcc/tree-affine.c (working copy) *************** add_elt_to_tree (tree expr, tree type, t *** 377,411 **** type1 = sizetype; scale = double_int_ext_for_comb (scale, comb); ! elt = fold_convert (type1, elt); if (scale.is_one ()) { if (!expr) ! return fold_convert (type, elt); ! if (POINTER_TYPE_P (type)) ! return fold_build_pointer_plus (expr, elt); ! return fold_build2 (PLUS_EXPR, type, expr, elt); } if (scale.is_minus_one ()) { if (!expr) ! return fold_convert (type, fold_build1 (NEGATE_EXPR, type1, elt)); ! if (POINTER_TYPE_P (type)) ! { ! elt = fold_build1 (NEGATE_EXPR, type1, elt); ! return fold_build_pointer_plus (expr, elt); ! } ! return fold_build2 (MINUS_EXPR, type, expr, elt); } if (!expr) ! return fold_convert (type, ! fold_build2 (MULT_EXPR, type1, elt, ! double_int_to_tree (type1, scale))); if (scale.is_negative ()) { --- 377,422 ---- type1 = sizetype; scale = double_int_ext_for_comb (scale, comb); ! ! if (scale.is_minus_one () ! && POINTER_TYPE_P (TREE_TYPE (elt))) ! { ! elt = fold_build1 (NEGATE_EXPR, sizetype, convert_to_ptrofftype (elt)); ! scale = double_int_one; ! } if (scale.is_one ()) { if (!expr) ! return elt; ! if (POINTER_TYPE_P (TREE_TYPE (expr))) ! return fold_build_pointer_plus (expr, convert_to_ptrofftype (elt)); ! if (POINTER_TYPE_P (TREE_TYPE (elt))) ! return fold_build_pointer_plus (elt, convert_to_ptrofftype (expr)); ! return fold_build2 (PLUS_EXPR, type1, ! fold_convert (type1, expr), ! fold_convert (type1, elt)); } if (scale.is_minus_one ()) { if (!expr) ! return fold_build1 (NEGATE_EXPR, TREE_TYPE (elt), elt); ! if (POINTER_TYPE_P (TREE_TYPE (expr))) ! return fold_build_pointer_plus ! (expr, convert_to_ptrofftype ! (fold_build1 (NEGATE_EXPR, TREE_TYPE (elt), elt))); ! return fold_build2 (MINUS_EXPR, type1, ! fold_convert (type1, expr), ! fold_convert (type1, elt)); } + elt = fold_convert (type1, elt); if (!expr) ! return fold_build2 (MULT_EXPR, type1, elt, ! double_int_to_tree (type1, scale)); if (scale.is_negative ()) { *************** add_elt_to_tree (tree expr, tree type, t *** 417,429 **** elt = fold_build2 (MULT_EXPR, type1, elt, double_int_to_tree (type1, scale)); ! if (POINTER_TYPE_P (type)) { if (code == MINUS_EXPR) elt = fold_build1 (NEGATE_EXPR, type1, elt); return fold_build_pointer_plus (expr, elt); } ! return fold_build2 (code, type, expr, elt); } /* Makes tree from the affine combination COMB. */ --- 428,441 ---- elt = fold_build2 (MULT_EXPR, type1, elt, double_int_to_tree (type1, scale)); ! if (POINTER_TYPE_P (TREE_TYPE (expr))) { if (code == MINUS_EXPR) elt = fold_build1 (NEGATE_EXPR, type1, elt); return fold_build_pointer_plus (expr, elt); } ! return fold_build2 (code, type1, ! fold_convert (type1, expr), elt); } /* Makes tree from the affine combination COMB. */ Index: gcc/testsuite/gcc.dg/tree-ssa/loop-4.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/loop-4.c (revision 202097) --- gcc/testsuite/gcc.dg/tree-ssa/loop-4.c (working copy) *************** void xxx(void) *** 37,43 **** /* { dg-final { scan-tree-dump-times " \\* \[^\\n\\r\]*=" 0 "optimized" } } */ /* { dg-final { scan-tree-dump-times "\[^\\n\\r\]*= \\* " 0 "optimized" } } */ ! /* { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } } */ /* And the original induction variable should be eliminated. */ --- 37,43 ---- /* { dg-final { scan-tree-dump-times " \\* \[^\\n\\r\]*=" 0 "optimized" } } */ /* { dg-final { scan-tree-dump-times "\[^\\n\\r\]*= \\* " 0 "optimized" } } */ ! /* { dg-final { scan-tree-dump-times " MEM" 1 "optimized" } } */ /* And the original induction variable should be eliminated. */