Roger,
However, the utility of early fold to the GCC compiler is much greater
than simply compile-time evaluating expressions with constant operands.
One of the reasons that fold is so fast, is that it can rely on the fact
that all of a trees operands have already been folded. In fact, much
of the middle-end makes or can make use of the assumptions that constant
operands to binary operators appear second, that a NOP_EXPRs only appear
where needed, that NEGATE_EXPR never wraps another NEGATE_EXPR and that
"x+x" and "2*x" are represented the same way.
I did not realize fold was non-recursive -- I thought it was, but maybe
I was hallucinating when I saw that :) Canonicalizing for the middle
end could, of course, happen during the gimplification stage.
For example, left to it's own devices a front-end would produce a
potentially unbounded tree for "!!!!!!!!!!!!!!...!!!!x". Whilst, it
might be desirable to reproduce such ugliness in source code analyis
tools, the fact that GCC currently only has to work minimal trees
(compact by construction) both improves compile-time and memory usage.
The current implementation does not have those properties -- because
each one of those !<expr>'s will have created a ! node, which is then
folded. You're correct that a fold_buildN interface would save memory
by not creating the to-be-folded node in the first place.
However, we've identified that early folding is getting in the way
of language conformance (Andrew Haley's java comments, there are some
icky cases with C, C++, floats and casts). It would be a pity not to
come up with a design that would allow those to be done correctly.
I wonder how much such non-reassociation/strength reduction folding
happens in a real program? Do we have some numbers on that?
Another example is the some front-ends (cough, g++, cough) love calling
save_expr at any opportunity, even on constant integers and string
literals. If it wasn't for the middle-end/fold only creating such
tree nodes as necessary, many analyses/transformations, would be
significantly complicated.
I'm don't understand your point here. save_expr only creates SAVE_EXPRs
on TREE_SIDE_EFFECTed nodes, doesn't it? Part of the problem with them
is the FE's love of lowering some FE construct to middle-end representation
early on, and of necessity refering to some operand more than one.
An example would be a c++ convert-to-base, which needs to generate something
like 'op ? op+base_offset : NULL' -- if the middle end used an FE
specific BASE_CONV node, the creation of a SAVE_EXPR could be delayed
until gimplification -- when constant evaluation/strength reduction
can be applied concurrently.
As several front-end people have suggested, calling fold whilst
constructing parse trees shouldn't be necessary (as shown by the
shining examples of g77 and GNAT). In reality, many of the
transformations performed by fold (most? as I expect expressions with
constant operands are actually fairly rare at the source level)
are purely to tidy up the inefficiencies or incorrect tree representations
constructed by the front-ends.
Er, should we really have a 'cleanup incorrect gunk' mechanism (much like
how reload fixes up all that dodgy RTL backends produce).
If it isn't clear from the name fold_buildN, these interfaces are
designed to apply the invariants expected when building trees. In
No it wasn't clear. I thought these would be doing more than making
canonical trees. I thought they would be doing the kind of reassociation
and strength reduction optimization that fold-const currently does.
Are they to do that as well? If they are just to make canonical trees,
can we have a less confusing name?
the further flung future, the buildN interfaces may become deprecated
and even further still trees might be marked read-only (i.e. const)
outside of the middle-end (allowing static trees and more middle-end
controlled tree sharing). Bwa-ha-ha-ha-ha (evil laugh)!
evil grin indeedy :)
nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
[EMAIL PROTECTED] :: http://www.planetfall.pwp.blueyonder.co.uk