This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix type correctness of fold_indirect_ref and fallout
- From: Richard Guenther <rguenth at tat dot physik dot uni-tuebingen dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 19 May 2005 11:13:50 +0200 (CEST)
- Subject: [PATCH] Fix type correctness of fold_indirect_ref and fallout
This series of patches fixes type correctness of fold_indirect_ref
and build_fold_indirect_ref and the missed-optimization / ICE fallout
resulting from it. The tree-inline.c part was approved by rth
separately, the fold_indirect_ref change was considered ok by Roger
on IRC if regressions were addressed.
This patch series passed bootstrap and regtesting on
x86_64-unknown-linux-gnu for all languages but ada with a tree
containing the cfg-inliner and Jeffs forward-prop change
(top of ChangeLog is
2005-05-18 Geoffrey Keating <geoffk@apple.com>
* dummy-checksum.c: New.
* genchecksum.c: New.
) - I believe it will not cause any problems noticed by the testsuite.
Ok for mainline?
Thanks,
Richard.
2005-05-18 Richard Guenther <rguenth@gcc.gnu.org>
* tree-inline.c (copy_body_r): Manually fold *& to deal
with ADDR_EXPRs with mismatched types for now.
2005-05-17 Richard Guenther <rguenth@gcc.gnu.org>
* gimplify.c (fold_indirect_ref_rhs): New function.
(gimplify_modify_expr_rhs): Use it instead of pessimistic
fold_indirect_ref.
2005-05-15 Richard Guenther <rguenth@gcc.gnu.org>
* fold-const.c (fold_indirect_ref_1): Add type argument;
make sure the resulting expression is of this type.
(build_fold_indirect_ref, fold_indirect_ref): Adjust callers.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.581
diff -c -3 -p -r1.581 fold-const.c
*** fold-const.c 17 May 2005 09:55:20 -0000 1.581
--- fold-const.c 19 May 2005 08:58:41 -0000
*************** build_fold_addr_expr (tree t)
*** 11448,11461 ****
return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t)));
}
! /* Given a pointer value T, return a simplified version of an indirection
! through T, or NULL_TREE if no simplification is possible. */
static tree
! fold_indirect_ref_1 (tree t)
{
! tree type = TREE_TYPE (TREE_TYPE (t));
! tree sub = t;
tree subtype;
STRIP_NOPS (sub);
--- 11448,11461 ----
return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t)));
}
! /* Given a pointer value OP0 and a type TYPE, return a simplified version
! of an indirection through OP0, or NULL_TREE if no simplification is
! possible. */
static tree
! fold_indirect_ref_1 (tree type, tree op0)
{
! tree sub = op0;
tree subtype;
STRIP_NOPS (sub);
*************** fold_indirect_ref_1 (tree t)
*** 11468,11478 ****
tree op = TREE_OPERAND (sub, 0);
tree optype = TREE_TYPE (op);
/* *&p => p */
! if (lang_hooks.types_compatible_p (type, optype))
return op;
/* *(foo *)&fooarray => fooarray[0] */
else if (TREE_CODE (optype) == ARRAY_TYPE
! && lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
{
tree type_domain = TYPE_DOMAIN (optype);
tree min_val = size_zero_node;
--- 11468,11478 ----
tree op = TREE_OPERAND (sub, 0);
tree optype = TREE_TYPE (op);
/* *&p => p */
! if (type == optype)
return op;
/* *(foo *)&fooarray => fooarray[0] */
else if (TREE_CODE (optype) == ARRAY_TYPE
! && type == TREE_TYPE (optype))
{
tree type_domain = TYPE_DOMAIN (optype);
tree min_val = size_zero_node;
*************** fold_indirect_ref_1 (tree t)
*** 11484,11490 ****
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
! && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
{
tree type_domain;
tree min_val = size_zero_node;
--- 11484,11490 ----
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
! && type == TREE_TYPE (TREE_TYPE (subtype)))
{
tree type_domain;
tree min_val = size_zero_node;
*************** fold_indirect_ref_1 (tree t)
*** 11504,11515 ****
tree
build_fold_indirect_ref (tree t)
{
! tree sub = fold_indirect_ref_1 (t);
if (sub)
return sub;
else
! return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
}
/* Given an INDIRECT_REF T, return either T or a simplified version. */
--- 11504,11516 ----
tree
build_fold_indirect_ref (tree t)
{
! tree type = TREE_TYPE (TREE_TYPE (t));
! tree sub = fold_indirect_ref_1 (type, t);
if (sub)
return sub;
else
! return build1 (INDIRECT_REF, type, t);
}
/* Given an INDIRECT_REF T, return either T or a simplified version. */
*************** build_fold_indirect_ref (tree t)
*** 11517,11523 ****
tree
fold_indirect_ref (tree t)
{
! tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0));
if (sub)
return sub;
--- 11518,11524 ----
tree
fold_indirect_ref (tree t)
{
! tree sub = fold_indirect_ref_1 (TREE_TYPE (t), TREE_OPERAND (t, 0));
if (sub)
return sub;
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.126
diff -c -3 -p -r2.126 gimplify.c
*** gimplify.c 1 May 2005 23:23:33 -0000 2.126
--- gimplify.c 19 May 2005 09:07:42 -0000
*************** gimplify_init_constructor (tree *expr_p,
*** 2846,2851 ****
--- 2846,2907 ----
return GS_ALL_DONE;
}
+ /* Given a pointer value OP0, return a simplified version of an
+ indirection through OP0, or NULL_TREE if no simplification is
+ possible. This may only be applied to a rhs of an expression.
+ Note that the resulting type may be different from the type pointed
+ to in the sense that it is still compatible from the langhooks
+ point of view. */
+
+ static tree
+ fold_indirect_ref_rhs (tree t)
+ {
+ tree type = TREE_TYPE (TREE_TYPE (t));
+ tree sub = t;
+ tree subtype;
+
+ STRIP_NOPS (sub);
+ subtype = TREE_TYPE (sub);
+ if (!POINTER_TYPE_P (subtype))
+ return NULL_TREE;
+
+ if (TREE_CODE (sub) == ADDR_EXPR)
+ {
+ tree op = TREE_OPERAND (sub, 0);
+ tree optype = TREE_TYPE (op);
+ /* *&p => p */
+ if (lang_hooks.types_compatible_p (type, optype))
+ return op;
+ /* *(foo *)&fooarray => fooarray[0] */
+ else if (TREE_CODE (optype) == ARRAY_TYPE
+ && lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
+ {
+ tree type_domain = TYPE_DOMAIN (optype);
+ tree min_val = size_zero_node;
+ if (type_domain && TYPE_MIN_VALUE (type_domain))
+ min_val = TYPE_MIN_VALUE (type_domain);
+ return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
+ }
+ }
+
+ /* *(foo *)fooarrptr => (*fooarrptr)[0] */
+ if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
+ && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
+ {
+ tree type_domain;
+ tree min_val = size_zero_node;
+ sub = fold_indirect_ref_rhs (sub);
+ if (! sub)
+ sub = build1 (INDIRECT_REF, TREE_TYPE (subtype), sub);
+ type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
+ if (type_domain && TYPE_MIN_VALUE (type_domain))
+ min_val = TYPE_MIN_VALUE (type_domain);
+ return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
+ }
+
+ return NULL_TREE;
+ }
+
/* Subroutine of gimplify_modify_expr to do simplifications of MODIFY_EXPRs
based on the code of the RHS. We loop for as long as something changes. */
*************** gimplify_modify_expr_rhs (tree *expr_p,
*** 2869,2876 ****
This kind of code arises in C++ when an object is bound
to a const reference, and if "x" is a TARGET_EXPR we want
to take advantage of the optimization below. */
! tree t = fold_indirect_ref (*from_p);
! if (t != *from_p)
{
*from_p = t;
ret = GS_OK;
--- 2925,2932 ----
This kind of code arises in C++ when an object is bound
to a const reference, and if "x" is a TARGET_EXPR we want
to take advantage of the optimization below. */
! tree t = fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0));
! if (t)
{
*from_p = t;
ret = GS_OK;
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.185
diff -c -3 -p -r1.185 tree-inline.c
*** tree-inline.c 17 May 2005 16:56:27 -0000 1.185
--- tree-inline.c 19 May 2005 08:58:43 -0000
*************** copy_body_r (tree *tp, int *walk_subtree
*** 613,619 ****
n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
if (n)
{
! *tp = build_fold_indirect_ref ((tree)n->value);
*walk_subtrees = 0;
return NULL;
}
--- 613,629 ----
n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
if (n)
{
! /* If we happen to get an ADDR_EXPR in n->value, strip
! it manually here as we'll eventually get ADDR_EXPRs
! which lie about their types pointed to. In this case
! build_fold_indirect_ref wouldn't strip the INDIRECT_REF,
! but we absolutely rely on that. */
! if (TREE_CODE ((tree)n->value) == ADDR_EXPR)
! *tp = TREE_OPERAND ((tree)n->value, 0);
! else
! *tp = build1 (INDIRECT_REF,
! TREE_TYPE (TREE_TYPE ((tree)n->value)),
! (tree)n->value);
*walk_subtrees = 0;
return NULL;
}