re PR middle-end/52720 (internal compiler error: in try_move_mult_to_index)

2012-03-27  Richard Guenther  <rguenther@suse.de>

	PR middle-end/52720
	* fold-const.c (try_move_mult_to_index): Handle &x.array more
	explicitely.

	* gcc.dg/torture/pr52720.c: New testcase.

From-SVN: r185864
This commit is contained in:
Richard Guenther 2012-03-27 12:49:10 +00:00 committed by Richard Biener
parent d54cef6248
commit 4da3c5cc2d
4 changed files with 116 additions and 77 deletions

View File

@ -1,3 +1,9 @@
2012-03-27 Richard Guenther <rguenther@suse.de>
PR middle-end/52720
* fold-const.c (try_move_mult_to_index): Handle &x.array more
explicitely.
2012-03-24 Eric Botcazou <ebotcazou@adacore.com>
PR target/52610

View File

@ -6850,6 +6850,78 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
s = integer_one_node;
}
/* Handle &x.array the same as we would handle &x.array[0]. */
if (TREE_CODE (ref) == COMPONENT_REF
&& TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
{
tree domain;
/* Remember if this was a multi-dimensional array. */
if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
mdim = true;
domain = TYPE_DOMAIN (TREE_TYPE (ref));
if (! domain)
goto cont;
itype = TREE_TYPE (domain);
step = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref)));
if (TREE_CODE (step) != INTEGER_CST)
goto cont;
if (s)
{
if (! tree_int_cst_equal (step, s))
goto cont;
}
else
{
/* Try if delta is a multiple of step. */
tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, op1, step);
if (! tmp)
goto cont;
delta = tmp;
}
/* Only fold here if we can verify we do not overflow one
dimension of a multi-dimensional array. */
if (mdim)
{
tree tmp;
if (!TYPE_MIN_VALUE (domain)
|| !TYPE_MAX_VALUE (domain)
|| TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
goto cont;
tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
fold_convert_loc (loc, itype,
TYPE_MIN_VALUE (domain)),
fold_convert_loc (loc, itype, delta));
if (TREE_CODE (tmp) != INTEGER_CST
|| tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
goto cont;
}
/* We found a suitable component reference. */
pref = TREE_OPERAND (addr, 0);
ret = copy_node (pref);
SET_EXPR_LOCATION (ret, loc);
ret = build4_loc (loc, ARRAY_REF, TREE_TYPE (TREE_TYPE (ref)), ret,
fold_build2_loc
(loc, PLUS_EXPR, itype,
fold_convert_loc (loc, itype,
TYPE_MIN_VALUE
(TYPE_DOMAIN (TREE_TYPE (ref)))),
fold_convert_loc (loc, itype, delta)),
NULL_TREE, NULL_TREE);
return build_fold_addr_expr_loc (loc, ret);
}
cont:
for (;; ref = TREE_OPERAND (ref, 0))
{
if (TREE_CODE (ref) == ARRAY_REF)
@ -6904,60 +6976,6 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
continue;
}
break;
}
else if (TREE_CODE (ref) == COMPONENT_REF
&& TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
{
tree domain;
/* Remember if this was a multi-dimensional array. */
if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
mdim = true;
domain = TYPE_DOMAIN (TREE_TYPE (ref));
if (! domain)
continue;
itype = TREE_TYPE (domain);
step = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref)));
if (TREE_CODE (step) != INTEGER_CST)
continue;
if (s)
{
if (! tree_int_cst_equal (step, s))
continue;
}
else
{
/* Try if delta is a multiple of step. */
tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, op1, step);
if (! tmp)
continue;
delta = tmp;
}
/* Only fold here if we can verify we do not overflow one
dimension of a multi-dimensional array. */
if (mdim)
{
tree tmp;
if (!TYPE_MIN_VALUE (domain)
|| !TYPE_MAX_VALUE (domain)
|| TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
continue;
tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
fold_convert_loc (loc, itype,
TYPE_MIN_VALUE (domain)),
fold_convert_loc (loc, itype, delta));
if (TREE_CODE (tmp) != INTEGER_CST
|| tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
continue;
}
break;
}
else
@ -6982,29 +7000,11 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
pos = TREE_OPERAND (pos, 0);
}
if (TREE_CODE (ref) == ARRAY_REF)
{
TREE_OPERAND (pos, 1)
= fold_build2_loc (loc, PLUS_EXPR, itype,
fold_convert_loc (loc, itype, TREE_OPERAND (pos, 1)),
fold_convert_loc (loc, itype, delta));
return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret);
}
else if (TREE_CODE (ref) == COMPONENT_REF)
{
gcc_assert (ret == pos);
ret = build4_loc (loc, ARRAY_REF, TREE_TYPE (TREE_TYPE (ref)), ret,
fold_build2_loc
(loc, PLUS_EXPR, itype,
fold_convert_loc (loc, itype,
TYPE_MIN_VALUE
(TYPE_DOMAIN (TREE_TYPE (ref)))),
fold_convert_loc (loc, itype, delta)),
NULL_TREE, NULL_TREE);
return build_fold_addr_expr_loc (loc, ret);
}
else
gcc_unreachable ();
TREE_OPERAND (pos, 1)
= fold_build2_loc (loc, PLUS_EXPR, itype,
fold_convert_loc (loc, itype, TREE_OPERAND (pos, 1)),
fold_convert_loc (loc, itype, delta));
return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret);
}

View File

@ -1,3 +1,8 @@
2012-03-27 Richard Guenther <rguenther@suse.de>
PR middle-end/52720
* gcc.dg/torture/pr52720.c: New testcase.
2012-03-26 Georg-Johann Lay <avr@gjlay.de>
Backport from 2012-03-26 mainline r185793.

View File

@ -0,0 +1,28 @@
/* { dg-do compile } */
/* { dg-options "-march=k8-sse3" { target x86_64-*-* } } */
struct alu_bank_swizzle {
int hw_gpr[3][4];
int hw_cfile_addr[4];
};
static void init_bank_swizzle(struct alu_bank_swizzle *bs)
{
int i, cycle, component;
for (cycle = 0; cycle < 3; cycle++)
for (component = 0; component < 4; component++)
bs->hw_gpr[cycle][component] = -1;
for (i = 0; i < 4; i++)
bs->hw_cfile_addr[i] = -1;
}
int check_and_set_bank_swizzle(int max_slots, int *slots)
{
struct alu_bank_swizzle bs;
int i;
for (i = 0; i < max_slots; i++)
{
init_bank_swizzle(&bs);
if (slots[i])
check_vector(&bs);
}
}