Quoting "Joseph S. Myers" <jos...@codesourcery.com>:
On Mon, 15 Nov 2010, Joern Rennecke wrote:
With 638 macros documented by @defmac, and 475 files that include tm.h ,
our current approach to hookization is too slow to get the tree optimizers
and front ends independent of target macros in any useful timeframe.
I think it's perfectly feasible; I think the two-person year estimate I
mentioned in <http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02675.html> for
a project that would include a lot more than just eliminating target
macros is realistic.
I was more thinking of getting the frontend and tree optimizers weaned off
target macros within one to four weeks.
A complete conversion of OPTIMIZATION_OPTIONS - a macro defined by lots of
targets - took me about five hours' work. Many macros are defined by far
fewer targets and would be much quicker to convert. Similarly, creating a
wrapper in targhooks.c is much quicker than doing a complete conversion of
a macro to a hook for all targets at one go.
Still, there are so many of them, and we can't reap the benefits till we
have covered all the ones that are used outside of the rtl centric files.
(Those macros that are referenced in libgcc or other target code, in the
driver, etc., or in #if etc. conditionals, are of course harder.)
Indeed. As I said, I intend to focus for the time being on the parts used
in the compiler proper, i.e. cc1, cc1plus etc.
By wrapper hooks you mean hooks in targhooks.c like the present
transitional system?
Yes, except that for most of the hooks, I expect to select only the
argument / return types, and let a new or extended generator program
write the hook code. Some types would nominally have an enum, but actually
use integers, and be casted in the relevant places. That, too, is supposed
to be handled by the autogeneration program.
That seems reasonable, but I really don't see the benefit of the wrapper
macros; they seem like needless complication.
It lets be focus on the part that needs to be done now to get frontend /
tree-optimizer independence from target macros, i.e. define the set
of autoconverted macros and their types, and handle any exceptional
cases.
If the hook is defined to
have the same semantics as the macro, changing the uses to use the hook
directly is just search-and-replace (plus reformatting if lines go over 80
characters).
Yes, but search-and-replace and reformatting for so many macros is also a
lot of work (if you think ident can do the job, I'd like to see a patch
submission to indent to do correct and conservative reformatting of
GCC sources). Plus, it generates a lot of repository churn.
And the target hook names will probably not be final, so you'd have to
search-and-replace after each hook name or site (targetm sub-struct)
change.
I'll create all the wrapper hooks initially as sub-members of a new
targetm.wrapper member; If people would like them somewhere else, we can
move them around later, but discussing individual placement of some
sixhundred hooks beforehand would just slow down things too much.
I do not believe this is sensible. A key point of macro-to-hook
conversion is to clean up the compiler's target interface, which means
thinking individually about the correct hook form of each interface.
As I said, I'll have to assign argument and return types for each wrapper.
That is already an important part of this work. And if any lvalue or
label arguments appear, that'll need special handling too.
By keeping the conceptually trivial stuff trivial we can focus on the
stuff that actually needs special attention.
Plus, if you want every hook to be well-named and designed, you can see
all the members of targetm.wrapper as a to-do list of hooks that should be
placed in a semantics-related place, possibly renamed etc.
A
pile of automatically generated wrappers is hardly better than a pile of
macros,
It is a useful first step to a better defined target hook interface, and
it will allow us to get rid of dependencies that currently prevent us from
better modularizing the compiler.
and it is often the case that a one-to-one correspondence of
macros and hooks is not appropriate.
I expect I'll find some such cases, which I'll have to deal on a case-by-case
basis. That's not a reason to elevate the difficulty of each detail to the
difficulty of the hardest detail.
It's much better to work in thematic
groups.
My theme is 'everything that gets in the way of a multi-target compiler'.
I understand that you probably mean that you like the hooks grouped together
by theme, like asm_out etc. Everyone had years to do that, yet the job is
still not done.
You can still re-organize things after I create the wrapper infrastructure;
in fact, I think it'll be easier, since you can focus on what is really
relevant. E.g. there is little point is replacing every scheduler and
reload macro, unless you want to rewrite most of that code to get rid of
all the #if directives too. Simple, concise macros like Pmode or
FIRST_PSEUDO_REGISTER make sense in code that should be specialized for
each target for performance reasons. You could do this with C++ templates
and LTO, but it'd just make compiler debugging so much harder.
I have previously considered the question of how you identify all target
macros to know that a conversion is complete. My conclusion is:
Define a target macro for this purpose to be a macro defined in a config/
header listed in tm_file and used in a source file outside of config/.
This is not sufficient for a multi-target compiler of the form I was
considering - there are macros such as HAVE_<insn> that are defined by
generator programs and tested in front ends,
That is true. We probably want a bitmap of the named patterns for which
the frontends want to test HAVE_xxx, unless the use can be easily replaced
with an optabs query - the latter might work if the frontend wants to know
if an expander is available, but not if the question is if a particular
code generation is suitable because of particular hardware support.
Some of these tests might be better of having special hooks - but again,
there is no limit to the amount of refinements we can make, and if we require
all possible refinements to be present in v1.0, v1.0 will never be.
and those such as DELAY_SLOTS
and INSN_SCHEDULING that similarly are defined by generator programs (but
at least those two are not tested in front ends).
Indeed, I see no need to change such macros as long as they are only used
by rtl passes. It ain't broken...
And there are also
target macros that only get tested in other files in config/. But it is
still a very useful step in cleaning up the target interfaces in the
compiler.
Depending on what the config files do, I might need to address this too
in order to get a multi-target compiler going. But I'll be content to
start out with being able to link two specific backends together - fixes
to get more backends into shape can be added later.
Then any target macro must have at least one of the following properties:
* The macro is tested with #if/#ifdef/#ifndef/#elif in a source file
outside of config/ (but including front-end subdirectories). Care is
needed in identifying such macros through grep because of
backslash-newline line continuations and because it's possible some macros
are only tested in generated files not directly in source files. Of
course lots of macros tested in preprocessor conditionals will not be
target macros, but you need to check the definitions of such macros to
find any cases such as:
#define FOO TARGET_MACRO
#if FOO
I will have to be wary of those, and they'll indeed will need code changes.
* The macro is defined by every target. Such macros could be found by
going through all the headers in tm_file for some single convenient target
that does not have too much defined in the headers listed there.
This is not a very useful criterion, because it covers so many macros that
are not used outside the rtl passes. It'd have to be filtered against
what is actually used. OTOH grep will be left blind-sided by token-pasting,
so trying to build for lots of targets will be an important test, too.
This is why I've been working on PR44756 first.