diff options
author | Jason Merrill <jason@redhat.com> | 2010-11-01 21:20:42 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-11-01 21:20:42 -0400 |
commit | 7bf8ca763de168f22d2b65662a83e47b56d187e8 (patch) | |
tree | 56a4b5dc694a3d3f2da85636c53092dae364d937 /gcc | |
parent | 878415841a34cf750c5ca0573161cc528e4a51a9 (diff) | |
download | gcc-7bf8ca763de168f22d2b65662a83e47b56d187e8.zip gcc-7bf8ca763de168f22d2b65662a83e47b56d187e8.tar.gz gcc-7bf8ca763de168f22d2b65662a83e47b56d187e8.tar.bz2 |
fold-const.c (fold_indirect_ref_1): Handle folding POINTER_PLUS_EXPR to ARRAY_REF.
* fold-const.c (fold_indirect_ref_1): Handle folding
POINTER_PLUS_EXPR to ARRAY_REF.
From-SVN: r166163
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/fold-const.c | 78 |
2 files changed, 47 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e0e3e22..eedc19b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2010-11-01 Jason Merrill <jason@redhat.com> + + * fold-const.c (fold_indirect_ref_1): Handle folding + POINTER_PLUS_EXPR to ARRAY_REF. + 2010-11-01 Kaz Kojima <kkojima@gcc.gnu.org> * config/sh/sh.c (TARGET_DELEGITIMIZE_ADDRESS): Redefine. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 4599a69..67268ad 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -15643,53 +15643,59 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) } } - /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */ if (TREE_CODE (sub) == POINTER_PLUS_EXPR && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST) { tree op00 = TREE_OPERAND (sub, 0); tree op01 = TREE_OPERAND (sub, 1); - tree op00type; STRIP_NOPS (op00); - op00type = TREE_TYPE (op00); - if (TREE_CODE (op00) == ADDR_EXPR - && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE - && type == TREE_TYPE (TREE_TYPE (op00type))) + if (TREE_CODE (op00) == ADDR_EXPR) { - HOST_WIDE_INT offset = tree_low_cst (op01, 0); - tree part_width = TYPE_SIZE (type); - unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT; - unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; - tree index = bitsize_int (indexi); - - if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type))) - return fold_build3_loc (loc, - BIT_FIELD_REF, type, TREE_OPERAND (op00, 0), - part_width, index); + tree op00type; + op00 = TREE_OPERAND (op00, 0); + op00type = TREE_TYPE (op00); - } - } + /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */ + if (TREE_CODE (op00type) == VECTOR_TYPE + && type == TREE_TYPE (op00type)) + { + HOST_WIDE_INT offset = tree_low_cst (op01, 0); + tree part_width = TYPE_SIZE (type); + unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT; + unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; + tree index = bitsize_int (indexi); + if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type)) + return fold_build3_loc (loc, + BIT_FIELD_REF, type, op00, + part_width, index); - /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */ - if (TREE_CODE (sub) == POINTER_PLUS_EXPR - && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST) - { - tree op00 = TREE_OPERAND (sub, 0); - tree op01 = TREE_OPERAND (sub, 1); - tree op00type; - - STRIP_NOPS (op00); - op00type = TREE_TYPE (op00); - if (TREE_CODE (op00) == ADDR_EXPR - && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE - && type == TREE_TYPE (TREE_TYPE (op00type))) - { - tree size = TYPE_SIZE_UNIT (type); - if (tree_int_cst_equal (size, op01)) - return fold_build1_loc (loc, IMAGPART_EXPR, type, - TREE_OPERAND (op00, 0)); + } + /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */ + else if (TREE_CODE (op00type) == COMPLEX_TYPE + && type == TREE_TYPE (op00type)) + { + tree size = TYPE_SIZE_UNIT (type); + if (tree_int_cst_equal (size, op01)) + return fold_build1_loc (loc, IMAGPART_EXPR, type, op00); + } + /* ((foo *)&fooarray)[1] => fooarray[1] */ + else if (TREE_CODE (op00type) == ARRAY_TYPE + && type == TREE_TYPE (op00type)) + { + tree type_domain = TYPE_DOMAIN (op00type); + tree min_val = size_zero_node; + if (type_domain && TYPE_MIN_VALUE (type_domain)) + min_val = TYPE_MIN_VALUE (type_domain); + op01 = size_binop_loc (loc, EXACT_DIV_EXPR, op01, + TYPE_SIZE_UNIT (type)); + op01 = size_binop_loc (loc, PLUS_EXPR, op01, min_val); + op0 = build4 (ARRAY_REF, type, op00, op01, + NULL_TREE, NULL_TREE); + SET_EXPR_LOCATION (op0, loc); + return op0; + } } } |