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
--

Reply via email to