On fold_indirect_ref
Roger Sayle
roger@eyesopen.com
Sun May 15 16:00:00 GMT 2005
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;
This is the least intrusive and most correct change. Normally, in
fold-const.c the invariant is (or at least should be) that
gcc_assert (TREE_TYPE (t) == TREE_TYPE (fold (t))
Returning a tree with any type other than "type" from fold_indirect_ref
will potentially screw something up. Probably the reason that fold_unary
doesn't call fold_indirect_ref is precisely because it is unsafe.
If there are significant optimizations that require playing fast and
loose with optimization, then these really should me moved (back) out
of fold-const.c, to gimplify.c where the tree-ssa passes have a less
strict type system. Creating a gimplify_indirect_ref, or better still
both a gimplify_lhs_indirect_ref and a gimplify_rhs_indirect_ref would
allow these.
Not only, as you mention in your post, can't
float x;
*(int *)&x = 0x80000000;
validly be reduced to (int)x = 0x80000000, because of the need
for a cast on the lhs, but similarly, this transformation is just
as unsafe for the RHS, where
return *(int*)&x;
really isn't equivalent to (int)x, even when the front-end's language
hooks allow assignment/conversion from floats to ints and ints to
floats. Interpreting a float's bits as an integer isn't the same as
implicitly casting the float to an integer.
Likewise
int y;
return *(char*)y;
isn't always the same as (char)y depending up on the endianness of
the machine, even if ints can be assigned to chars by the front-end.
In the above cases, the usual casting operators NOP_EXPR and CONVERT_EXPR
are the wrong things to use. If these transformations are to be
performed at all, on both LHS and RHS, they must use VIEW_CONVERT_EXPR.
At the moment, it looks like if ever "optype != type" we're assuming
that the callers implicitly perform fold_convert or equivalent, which is
clearly the wrong form of conversion to use. The issue is that if ever
fold returns a type other than it's arguments, there's an ambiguity as
which form of conversion to use to correct it. In these cases, the
assumption that fold_convert can be used is incorrect.
You mentioned on IRC that many of the optimizers aren't expecting
VIEW_CONVERT_EXPRs, in which case it really is best to leave these
indirect references through casts of ADDR_EXPRs in their original form.
Roger
--
More information about the Gcc
mailing list