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