This fixes PR52720. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied on the trunk and the branch.
Richard. 2012-03-27 Richard Guenther <rguent...@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. Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c (revision 185725) --- gcc/fold-const.c (working copy) *************** try_move_mult_to_index (location_t loc, *** 6850,6913 **** s = integer_one_node; } ! for (;; ref = TREE_OPERAND (ref, 0)) { ! if (TREE_CODE (ref) == ARRAY_REF) ! { ! 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 (TREE_OPERAND (ref, 0))); ! if (! domain) ! continue; ! itype = TREE_TYPE (domain); ! step = array_ref_element_size (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 (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST ! || !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, ! TREE_OPERAND (ref, 1)), ! fold_convert_loc (loc, itype, delta)); ! if (!tmp ! || TREE_CODE (tmp) != INTEGER_CST ! || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp)) ! continue; ! } ! break; ! } ! else if (TREE_CODE (ref) == COMPONENT_REF ! && TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE) { tree domain; --- 6850,6930 ---- 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) { tree domain; *************** try_move_mult_to_index (location_t loc, *** 6915,6926 **** 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; --- 6932,6943 ---- if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF) mdim = true; ! domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0))); if (! domain) continue; itype = TREE_TYPE (domain); ! step = array_ref_element_size (ref); if (TREE_CODE (step) != INTEGER_CST) continue; *************** try_move_mult_to_index (location_t loc, *** 6944,6959 **** { 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; } --- 6961,6977 ---- { tree tmp; ! if (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST || !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, ! TREE_OPERAND (ref, 1)), fold_convert_loc (loc, itype, delta)); ! if (!tmp ! || TREE_CODE (tmp) != INTEGER_CST || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp)) continue; } *************** try_move_mult_to_index (location_t loc, *** 6982,7010 **** 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 (); } --- 7000,7010 ---- pos = TREE_OPERAND (pos, 0); } ! 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); } Index: gcc/testsuite/gcc.dg/torture/pr52720.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr52720.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr52720.c (revision 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); + } + } +