From 005aa1b4fba54dfc9f8a532ee82a8ac5f7257b9f Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Tue, 27 Mar 2012 12:50:29 +0000 Subject: [PATCH] re PR middle-end/52720 (internal compiler error: in try_move_mult_to_index) 2012-03-27 Richard Guenther 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: r185865 --- gcc/ChangeLog | 6 + gcc/fold-const.c | 154 ++++++++++++------------- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.dg/torture/pr52720.c | 28 +++++ 4 files changed, 116 insertions(+), 77 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr52720.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bf370df44ec..e9acac3165b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2012-03-27 Richard Guenther + + PR middle-end/52720 + * fold-const.c (try_move_mult_to_index): Handle &x.array more + explicitely. + 2012-03-27 Eric Botcazou * expmed.c (store_bit_field): Assert that BITREGION_START is a multiple diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 1e91bac9970..df0c05c6e02 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6826,6 +6826,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) @@ -6880,60 +6952,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 @@ -6958,29 +6976,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); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 63de5d4e7ba..408184a26b8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-03-27 Richard Guenther + + PR middle-end/52720 + * gcc.dg/torture/pr52720.c: New testcase. + 2012-03-27 Eric Botcazou * gnat.dg/pack17.adb: New test. diff --git a/gcc/testsuite/gcc.dg/torture/pr52720.c b/gcc/testsuite/gcc.dg/torture/pr52720.c new file mode 100644 index 00000000000..528aa161b13 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr52720.c @@ -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); + } +} +