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