Hi!

I have isolated the patch (attached) that caused the previously reported
build ICE and a testcase.  The patch enables folding of
&a[i] + cst to &a[i+cst] in addition to &a[i] + cst*j -> &a[i+j].
If enabled, this transformation triggeres two times in the
testcase derived from libiberty/sort.c:

#define UCHAR_MAX ((unsigned char)(-1))
#define DIGIT_MAX (UCHAR_MAX + 1)

void sort_pointers (void)
{
  unsigned int count[DIGIT_MAX];
  unsigned int *countp;

  for (countp = count + 1; countp < count + DIGIT_MAX; ++countp)
    ;
}

namely transforming

<PLUS
 <addr_expr 0x401467c0
    type <pointer_type 0x401b1bd0
        type <integer_type 0x4014957c unsigned int public unsigned SI
            size <integer_cst 0x40141408 constant invariant 32>
            unit size <integer_cst 0x40141198 constant invariant 4>
            align 32 symtab 0 alias set -1 precision 32 min <integer_cst 
0x40141480 0> max <integer_cst 0x40141468 4294967295>
            pointer_to_this <pointer_type 0x401b1bd0>>
        public unsigned SI size <integer_cst 0x40141408 32> unit size 
<integer_cst 0x40141198 4>
        align 32 symtab 0 alias set -1>
    invariant
    arg 0 <array_ref 0x401ba16c type <integer_type 0x4014957c unsigned int>

        arg 0 <var_decl 0x401b1c3c count type <array_type 0x401b1b64>
            addressable used BLK file t.c line 6
            size <integer_cst 0x401b6618 constant invariant 8192>
            unit size <integer_cst 0x401b6630 constant invariant 1024>
            align 32 context <function_decl 0x401b19b4 sort_pointers> chain 
<var_decl 0x401b1ca8 countp>>
        arg 1 <integer_cst 0x401b67f8 constant invariant 1>
        arg 2 <integer_cst 0x401411b0 constant invariant 0>
        arg 3 <integer_cst 0x40141228 constant invariant 1>>>
 <integer_cst 0x401b6678 type <pointer_type 0x401b1bd0> constant invariant 4>
>

to

 <addr_expr 0x40146ac0
    type <pointer_type 0x401b1bd0
        type <integer_type 0x4014957c unsigned int public unsigned SI
            size <integer_cst 0x40141408 constant invariant 32>
            unit size <integer_cst 0x40141198 constant invariant 4>
            align 32 symtab 0 alias set -1 precision 32 min <integer_cst 
0x40141480 0> max <integer_cst 0x40141468 4294967295>
            pointer_to_this <pointer_type 0x401b1bd0>>
        public unsigned SI size <integer_cst 0x40141408 32> unit size 
<integer_cst 0x40141198 4>
        align 32 symtab 0 alias set -1>
    invariant
    arg 0 <array_ref 0x401ba2d8 type <integer_type 0x4014957c unsigned int>

        arg 0 <var_decl 0x401b1c3c count type <array_type 0x401b1b64>
            addressable used BLK file t.c line 6
            size <integer_cst 0x401b6618 constant invariant 8192>
            unit size <integer_cst 0x401b6630 constant invariant 1024>
            align 32 context <function_decl 0x401b19b4 sort_pointers> chain 
<var_decl 0x401b1ca8 countp>>
        arg 1 <integer_cst 0x40141330 constant invariant 2>
        arg 2 <integer_cst 0x401411b0 constant invariant 0>
        arg 3 <integer_cst 0x40141228 constant invariant 1>>>

and
<PLUS
 <addr_expr 0x40146be0
    type <pointer_type 0x401b1bd0
        type <integer_type 0x4014957c unsigned int public unsigned SI
            size <integer_cst 0x40141408 constant invariant 32>
            unit size <integer_cst 0x40141198 constant invariant 4>
            align 32 symtab 0 alias set -1 precision 32 min <integer_cst 
0x40141480 0> max <integer_cst 0x40141468 4294967295>
            pointer_to_this <pointer_type 0x401b1bd0>>
        public unsigned SI size <integer_cst 0x40141408 32> unit size 
<integer_cst 0x40141198 4>
        align 32 symtab 0 alias set -1>
    invariant
    arg 0 <array_ref 0x401ba340 type <integer_type 0x4014957c unsigned int>

        arg 0 <var_decl 0x401b1c3c count type <array_type 0x401b1b64>
            addressable used BLK file t.c line 6
            size <integer_cst 0x401b6618 constant invariant 8192>
            unit size <integer_cst 0x401b6630 constant invariant 1024>
            align 32 context <function_decl 0x401b19b4 sort_pointers> chain 
<var_decl 0x401b1ca8 countp>>
        arg 1 <integer_cst 0x401b67f8 constant invariant 1>
        arg 2 <integer_cst 0x401411b0 constant invariant 0>
        arg 3 <integer_cst 0x40141228 constant invariant 1>>>
 <integer_cst 0x401b6678 type <pointer_type 0x401b1bd0> constant invariant 4>
>

to

 <addr_expr 0x40146cc0
    type <pointer_type 0x401b1bd0
        type <integer_type 0x4014957c unsigned int public unsigned SI
            size <integer_cst 0x40141408 constant invariant 32>
            unit size <integer_cst 0x40141198 constant invariant 4>
            align 32 symtab 0 alias set -1 precision 32 min <integer_cst 
0x40141480 0> max <integer_cst 0x40141468 4294967295>
            pointer_to_this <pointer_type 0x401b1bd0>>
        public unsigned SI size <integer_cst 0x40141408 32> unit size 
<integer_cst 0x40141198 4>
        align 32 symtab 0 alias set -1>
    invariant
    arg 0 <array_ref 0x401ba478 type <integer_type 0x4014957c unsigned int>

        arg 0 <var_decl 0x401b1c3c count type <array_type 0x401b1b64>
            addressable used BLK file t.c line 6
            size <integer_cst 0x401b6618 constant invariant 8192>
            unit size <integer_cst 0x401b6630 constant invariant 1024>
            align 32 context <function_decl 0x401b19b4 sort_pointers> chain 
<var_decl 0x401b1ca8 countp>>
        arg 1 <integer_cst 0x40141330 constant invariant 2>
        arg 2 <integer_cst 0x401411b0 constant invariant 0>
        arg 3 <integer_cst 0x40141228 constant invariant 1>>>

where I cannot find an errorneous transformation.  This triggers
a PRE ICE then:

/tmp/gcc-obj-checking/gcc/cc1 -quiet -v -I.
-I/net/alwazn/home/rguenth/src/gcc/gcc/libiberty/../include -iprefix
/tmp/gcc-obj-checking/gcc/../lib/gcc/i686-pc-linux-gnu/4.0.0/ -isystem
/tmp/gcc-obj-checking/gcc/include -DHAVE_CONFIG_H -isystem
/i686-pc-linux-gnu/include -isystem /i686-pc-linux-gnu/sys-include t.c
-quiet -dumpbase t.c -mtune=pentiumpro -auxbase-strip t.o -g -O2 -W -Wall
-pedantic -version -o /tmp/ccnVnHo2.s -fdump-tree-all
t.c: In function
'sort_pointers':
t.c:5: internal compiler error: in insert_aux, at tree-ssa-pre.c:1624
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.

where the dump before pre looks like

sort_pointers ()
{
  unsigned int * countp;
  unsigned int count[256];
  unsigned int * D.1137;

<bb 0>:

  # countp_1 = PHI <countp_4(3), &count[1](0)>;
<L0>:;
  countp_4 = countp_1 + 4B;
  if (countp_4 < &count[256]) goto <L6>; else goto <L2>;

<L6>:;
  goto <bb 1> (<L0>);

<L2>:;
  return;

}

Any idea how to debug what is going wrong?  Any PRE expert around?

Thanks,
Richard.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.511
diff -c -3 -p -r1.511 fold-const.c
*** fold-const.c        14 Feb 2005 16:07:08 -0000      1.511
--- fold-const.c        15 Feb 2005 10:15:11 -0000
*************** fold_sign_changed_comparison (enum tree_
*** 6184,6217 ****
  }
  
  /* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
!    step of the array.  ADDR is the address. MULT is the multiplicative 
expression.
!    If the function succeeds, the new address expression is returned.  
Otherwise
!    NULL_TREE is returned.  */
  
  static tree
! try_move_mult_to_index (enum tree_code code, tree addr, tree mult)
  {
!   tree s, delta, step;
!   tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1);
    tree ref = TREE_OPERAND (addr, 0), pref;
    tree ret, pos;
!   tree itype;
  
!   STRIP_NOPS (arg0);
!   STRIP_NOPS (arg1);
!   
!   if (TREE_CODE (arg0) == INTEGER_CST)
      {
!       s = arg0;
!       delta = arg1;
      }
!   else if (TREE_CODE (arg1) == INTEGER_CST)
      {
!       s = arg1;
!       delta = arg0;
      }
    else
!     return NULL_TREE;
  
    for (;; ref = TREE_OPERAND (ref, 0))
      {
--- 6184,6229 ----
  }
  
  /* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
!    step of the array.  Also handles the case of &a[idx] CODE delta with
!    delta being a constant multiple of the step of the array.
!    ADDR is the address. MULT is the multiplicative expression or the integer
!    constant offset. If the function succeeds, the new address expression is
!    returned.  Otherwise NULL_TREE is returned.  */
  
  static tree
! try_fold_into_array_ref (enum tree_code code, tree addr, tree mult)
  {
!   tree s = NULL_TREE, delta, step;
    tree ref = TREE_OPERAND (addr, 0), pref;
    tree ret, pos;
!   tree itype, type;
  
!   if (TREE_CODE (mult) == MULT_EXPR)
      {
!       tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1);
! 
!       STRIP_NOPS (arg0);
!       STRIP_NOPS (arg1);
!   
!       if (TREE_CODE (arg0) == INTEGER_CST)
!       {
!         s = arg0;
!         delta = arg1;
!       }
!       else if (TREE_CODE (arg1) == INTEGER_CST)
!       {
!         s = arg1;
!         delta = arg0;
!       }
!       else
!       return NULL_TREE;
      }
!   else if (TREE_CODE (mult) == INTEGER_CST)
      {
!       delta = mult;
      }
    else
!     gcc_unreachable ();
  
    for (;; ref = TREE_OPERAND (ref, 0))
      {
*************** try_move_mult_to_index (enum tree_code c
*** 6224,6245 ****
  
          itype = TREE_TYPE (step);
  
!         /* If the type sizes do not match, we might run into problems
!            when one of them would overflow.  */
!         if (TYPE_PRECISION (itype) != TYPE_PRECISION (TREE_TYPE (s)))
!           continue;
! 
!         if (!operand_equal_p (step, fold_convert (itype, s), 0))
!           continue;
! 
!         delta = fold_convert (itype, delta);
!         break;
        }
  
        if (!handled_component_p (ref))
        return NULL_TREE;
      }
  
    /* We found the suitable array reference.  So copy everything up to it,
       and replace the index.  */
  
--- 6236,6275 ----
  
          itype = TREE_TYPE (step);
  
!         if (s)
!           {
!             /* Try if the steps match.  */
!             if (tree_int_cst_equal (step, s))
!               break;
!           }
!         else
!           {
!             /* Try if delta is a multiple of step.  */
!             tree mod = int_const_binop (TRUNC_MOD_EXPR, delta, step, 0);
!             if (integer_zerop (mod))
!               {
!                 delta = int_const_binop (EXACT_DIV_EXPR, delta, step, 0);
!                 break;
!               }
!           }
        }
  
        if (!handled_component_p (ref))
        return NULL_TREE;
      }
  
+   /* Use the bigger type for the new offset.  */
+   if (TREE_CODE (TREE_OPERAND (ref, 1)) == INTEGER_CST
+       && TREE_CODE (delta) == INTEGER_CST)
+         type = itype;
+   else if (TREE_CODE (TREE_OPERAND (ref, 1)) == INTEGER_CST)
+         type = TREE_TYPE (delta);
+   else {
+       type = TREE_TYPE (TREE_OPERAND (ref, 1));
+       if (TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (delta)))
+               type = TREE_TYPE (delta);
+   }
+ 
    /* We found the suitable array reference.  So copy everything up to it,
       and replace the index.  */
  
*************** try_move_mult_to_index (enum tree_code c
*** 6254,6264 ****
        pos = TREE_OPERAND (pos, 0);
      }
  
!   TREE_OPERAND (pos, 1) = fold (build2 (code, itype,
!                                       TREE_OPERAND (pos, 1),
!                                       delta));
  
!   return build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
  }
  
  
--- 6284,6295 ----
        pos = TREE_OPERAND (pos, 0);
      }
  
!   TREE_OPERAND (pos, 1) = fold (build2 (code, type,
!                                       fold_convert (type, TREE_OPERAND (pos, 
1)),
!                                       fold_convert (type, delta)));
  
!   ret = build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
!   return ret;
  }
  
  
*************** fold (tree expr)
*** 7132,7147 ****
             of the array.  Loop optimizer sometimes produce this type of
             expressions.  */
          if (TREE_CODE (arg0) == ADDR_EXPR
!             && TREE_CODE (arg1) == MULT_EXPR)
            {
!             tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
              if (tem)
                return fold_convert (type, fold (tem));
            }
          else if (TREE_CODE (arg1) == ADDR_EXPR
!                  && TREE_CODE (arg0) == MULT_EXPR)
            {
!             tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
              if (tem)
                return fold_convert (type, fold (tem));
            }
--- 7163,7180 ----
             of the array.  Loop optimizer sometimes produce this type of
             expressions.  */
          if (TREE_CODE (arg0) == ADDR_EXPR
!             && (TREE_CODE (arg1) == MULT_EXPR
!                 || TREE_CODE (arg1) == INTEGER_CST))
            {
!             tem = try_fold_into_array_ref (PLUS_EXPR, arg0, arg1);
              if (tem)
                return fold_convert (type, fold (tem));
            }
          else if (TREE_CODE (arg1) == ADDR_EXPR
!                  && (TREE_CODE (arg0) == MULT_EXPR
!                      || TREE_CODE (arg0) == INTEGER_CST))
            {
!             tem = try_fold_into_array_ref (PLUS_EXPR, arg1, arg0);
              if (tem)
                return fold_convert (type, fold (tem));
            }
*************** fold (tree expr)
*** 7527,7535 ****
         of the array.  Loop optimizer sometimes produce this type of
         expressions.  */
        if (TREE_CODE (arg0) == ADDR_EXPR
!         && TREE_CODE (arg1) == MULT_EXPR)
        {
!         tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
          if (tem)
            return fold_convert (type, fold (tem));
        }
--- 7560,7569 ----
         of the array.  Loop optimizer sometimes produce this type of
         expressions.  */
        if (TREE_CODE (arg0) == ADDR_EXPR
!         && (TREE_CODE (arg1) == MULT_EXPR
!             || TREE_CODE (arg1) == INTEGER_CST))
        {
!         tem = try_fold_into_array_ref (MINUS_EXPR, arg0, arg1);
          if (tem)
            return fold_convert (type, fold (tem));
        }
 

Reply via email to