Hi,

On Thu, 8 Aug 2007, Ian Lance Taylor wrote:

those whose runtime type can be any derived one) can not. E.g. I wouldn't try to model the inheritance relationship.

There is some advantage to knowing class heirarchy relationships in LTO. Some C++ programs implement different virtual subclasses in different files. LTO can put those together. When the compiler can then determine that a variable definitely has a particular subclass, it can devirtualize the virtual calls, turning an indirect function call into a direct function calls, also exposing inlining opportunities.

Yes, devirtualization. But I wonder if you really need class hierarchies for this (actually I'm fairly sure you don't). In effect you only need to determine where this virtual call, when you know the definite runtime type of the object pointer, points to, i.e. to which function decl. For that you don't need the class hierarchy (i.e. the edges in the inheritance graph, or in fact any information about what base classes might or might exist or about other classes), but simply a list of all slot-number -> function-decls mappings for that type, i.e. the vtable (but let's call it different to not confuse it with the C++-ABI thingy which actually is written to the .o file). As the middle end should have all thunks already also 'this' pointer adjusting virtual calls should be taken care of (i.e. the slot->function mapping should already have the thunks referenced).

Then you just need a way to get from a definite type to that slot->function mapping. As the LTO frontend needs to emit something similar anyway somewhere (as it needs to express all C++ types in some lowered form appropriate for the LTO reader), it will be available somehow, presumably hanging off the RECORD_TYPE. If you have the definite runtime type of the pointer, you also have that RECORD_TYPE, hence the slot->function mapping, the slot number from the virtual call itself, and ergo the finally called function_decl. No need for hierarchies.

There were also other patches already floating around which (tried to) implement devirtualization (via profile feedback testing at runtime if a pointer was of certain type), which didn't need real inheritance hierarchies in the middle-end, so it can be done.

We also need to make sure to not munge together too many of these not entirely trivial topics. We have pointer to members (IMHO just fancy offsets) and virtual function calls (for devirtualization) up to now. They only relate via pointer to virtual member functions, which still are only fancy offsets (referring to a slot number, not a byte offset). So IMHO the C++ frontend should lower all these constructs as much as possible and try to express them in basic types and expressions, instead of pulling the whole hair into the middle end. If something is right now not possible in the middle-end, then we should try to carefully add the necessary information (and only that) to enable whatever we want. For devirtualization I think I pointed out one possibility. I'm not sure what else we want. Surely I've seen nothing which would make me think "hell, yes, let's pull pointer to members into the middle end, and as we are at it, let's add virtual functions right away too" ;-)


Ciao,
Michael.

PS: From time to time I'm forced to dive into either of these areas of cp/*.[ch] and it has some very complex code. Most of it really front-end related I know, but intertwined with the code generation and layouting code. I'm fairly certain that this all should stay in cp/ .

Reply via email to