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));
}