Roger Sayle wrote:
> On Sun, 15 May 2005, Richard Guenther wrote:
>
>>What can be done about this issues? First, we can use VIEW_CONVERT_EXPR
>>unconditionally in fold_indirect_ref and only break some optimizations
>>(like temp1.C). Second, we can declare fold_indirect_ref being unsafe
>>about types and deal with this in its callers where we possibly know
>>about if we're dealing with lvalues or rvalues, using either NOP_EXPRs
>>or VIEW_CONVERT_EXPRs as appropriate. We could ease this with providing
>>wrappers around fold_indirect_ref (or a flag) - but checking if we're
>>(possibly) dealing with a lhs is not possible, so uses may remain
>>unsafe.
>
>
> Exactly which optimization do we miss by changing:
>
> /* *&p => p */
> - if (lang_hooks.types_compatible_p (type, optype))
> + if (type == optype)
> return op;
I don't know - maybe stripping sign casts. But if we use equality
comparison here we can as well use STRIP_TYPE_NOPS instead of
STRIP_NOPS - but the patch doing so caused some optimization regressions.
If we want to simplify fold_indirect_ref_1 this way and enforce
type before == type after I can prepare a patch to do so. Meanwhile
a patch that survived some testing is attached for reference - it
does fix some type issues but leaves the fixing of the types to
fold_indirect_ref. Note that similarly build_fold_indirect_ref is
used in many places that look like they do not deal with mismatched
types.
Thanks for the input,
Richard.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.580
diff -c -3 -p -r1.580 fold-const.c
*** fold-const.c 14 May 2005 15:42:01 -0000 1.580
--- fold-const.c 15 May 2005 15:30:37 -0000
*************** fold_indirect_ref_1 (tree t)
*** 11420,11437 ****
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;
--- 11427,11447 ----
return op;
/* *(foo *)&fooarray => fooarray[0] */
else if (TREE_CODE (optype) == ARRAY_TYPE
+ /* FIXME unnecessary? */
&& 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, TREE_TYPE (optype),
! op, min_val, NULL_TREE, NULL_TREE);
}
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
+ /* FIXME unnecessary? */
&& lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE
(subtype))))
{
tree type_domain;
*************** fold_indirect_ref_1 (tree t)
*** 11440,11453 ****
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;
}
/* Builds an expression for an indirection through T, simplifying some
! cases. */
tree
build_fold_indirect_ref (tree t)
--- 11450,11465 ----
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, TREE_TYPE (TREE_TYPE (sub)),
! sub, min_val, NULL_TREE, NULL_TREE);
}
return NULL_TREE;
}
/* Builds an expression for an indirection through T, simplifying some
! cases. Note that the type of the resulting expression does not
! necessarily match that of the type pointed to by T. */
tree
build_fold_indirect_ref (tree t)
*************** tree
*** 11466,11476 ****
fold_indirect_ref (tree t)
{
tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0));
! if (sub)
return sub;
else
! return t;
}
/* Strip non-trapping, non-side-effecting tree nodes from an expression
--- 11478,11492 ----
fold_indirect_ref (tree t)
{
tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0));
+ if (! sub)
+ return t;
! if (TREE_TYPE (sub) == TREE_TYPE (t))
return sub;
+ else if (maybe_lvalue_p (sub))
+ return fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (t), sub);
else
! return fold_convert (TREE_TYPE (t), sub);
}
/* Strip non-trapping, non-side-effecting tree nodes from an expression