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.  */
  

Reply via email to