aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-11-01 21:20:42 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-11-01 21:20:42 -0400
commit7bf8ca763de168f22d2b65662a83e47b56d187e8 (patch)
tree56a4b5dc694a3d3f2da85636c53092dae364d937 /gcc/fold-const.c
parent878415841a34cf750c5ca0573161cc528e4a51a9 (diff)
downloadgcc-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/fold-const.c')
-rw-r--r--gcc/fold-const.c78
1 files changed, 42 insertions, 36 deletions
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;
+ }
}
}