Patchwork RFA: PR44566: accessor macros (1/3): CUMULATIVE_ARGS

login
register
mail settings
Submitter Joern Rennecke
Date June 24, 2010, 7:02 p.m.
Message ID <20100624150200.roql5i8jkwo8sk88-nzlynne@webmail.spamcop.net>
Download mbox | patch
Permalink /patch/56818/
State New
Headers show

Comments

Joern Rennecke - June 24, 2010, 7:02 p.m.
This fixes up the uses of crtl->args.info .

Bootstrapped and regression tested on i686-pc-linux-gnu in revision 161310.

There is still an issue with all the target hooks that have CUMULATIVE_ARGS
parameters.  This could either be fixed up by changing the function paraemter
types in very port - which would be a very large patch - or by introducing
a wrapper layer that calls the actual target hook function which continues
to use the target's CUMULATIVE_ARGS - but then, the wrapper would cost  
the overhead of an extra function call.

For the time being, it works well enough with placing a few more  
START_TARGET_SPECIFIC / END_TARGET_SPECIFIC markers in the tm.c of  
targets
that are used in multi-target configurations.  The gcc source compiled in
a multi-target configuration is not stricty conforming because of pointer
type punning from one target to the other on the target hook interface, but
at least when building with gcc, you would have to build gcc with aggressive
link-time optimization for that to matter.  If we have and can afford that,
than the wrapper solution might be essentially free - except someone will
have to find time to code it.
2010-06-24  Joern Rennecke  <joern.rennecke@embecosm.com>

	PR other/44566
	* function.h (target-gtypes.h): Include.
	(struct function): New member target_arch.
	* Makefile.in (TARGET_NUM): New Makefile variable.
	(cs-tm.h): Add TARGET_NUM to DEFINES.
	(GTFILES): Add target-gtypes.h.

	* function.h (struct incoming_args): Use type cumulative_args_u for
	member info.
	(INCOMING_ARGS_INFO): Define.
	* Makefile.in (target-gtypes.h, s-target-gtypes): New rules.

	* function.c (assign_parms): Use INCOMING_ARGS_INFO.

	* config/alpha/alpha.c (entire file): Replace crtl->args.info with
        INCOMING_ARGS_INFO (crtl->args).
	* config/xtensa/xtensa.c: Likewise.
	* config/sh/sh.md: Likewise.
	* config/sh/sh.c: Likewise.
	* config/arc/arc.c: Likewise.
	* config/mmix/mmix.c: Likewise.
	* config/m68hc11/m68hc11.c: Likewise.
	* config/sparc/sparc.c: Likewise.
	* config/ia64/ia64.c: Likewise.
	* config/avr/avr.c: Likewise.
	* config/stormy16/stormy16.c: Likewise.
	* config/iq2000/iq2000.c: Likewise.
	* config/frv/frv.c: Likewise.
	* config/mips/mips.c: Likewise.
	* config/spu/spu.c: Likewise.
	* config/v850/v850.c: Likewise.
	* config/s390/s390.c: Likewise.
	* config/rs6000/rs6000.c: Likewise.
	* config/arm/arm.c: Likewise.
	* config/i386/i386.c: Likewise.
Steven Bosscher - June 24, 2010, 7:18 p.m.
On Thu, Jun 24, 2010 at 9:02 PM, Joern Rennecke <amylaar@spamcop.net> wrote:
> This fixes up the uses of crtl->args.info .
>
> Bootstrapped and regression tested on i686-pc-linux-gnu in revision 161310.
>
> There is still an issue with all the target hooks that have CUMULATIVE_ARGS
> parameters.  This could either be fixed up by changing the function
> paraemter
> types in very port - which would be a very large patch

Nathan, didn't you promise a patch for this?? ;-)

Ciao!
Steven
Joern Rennecke - June 24, 2010, 7:46 p.m.
Quoting Steven Bosscher <stevenb.gcc@gmail.com>:

> On Thu, Jun 24, 2010 at 9:02 PM, Joern Rennecke <amylaar@spamcop.net> wrote:
>> This fixes up the uses of crtl->args.info .
>>
>> Bootstrapped and regression tested on i686-pc-linux-gnu in revision 161310.
>>
>> There is still an issue with all the target hooks that have CUMULATIVE_ARGS
>> parameters.  This could either be fixed up by changing the function
>> paraemter
>> types in very port - which would be a very large patch
>
> Nathan, didn't you promise a patch for this?? ;-)

This irony is that everything works just fine with the old-style target
macros wrapped into target hooks in targhooks.c : A single change to the
targhooks.c implementation fixes the interface.
However, with target hook directly implemented in tm.c, each tm.c has to be
fixed.
Unless we go the route of adding another wrapper function.
Nathan Froyd - June 25, 2010, 1:42 a.m.
On Thu, Jun 24, 2010 at 09:18:05PM +0200, Steven Bosscher wrote:
> On Thu, Jun 24, 2010 at 9:02 PM, Joern Rennecke <amylaar@spamcop.net> wrote:
> > This fixes up the uses of crtl->args.info .
> >
> > There is still an issue with all the target hooks that have CUMULATIVE_ARGS
> > parameters.  This could either be fixed up by changing the function
> > paraemter
> > types in very port - which would be a very large patch
> 
> Nathan, didn't you promise a patch for this?? ;-)

I don't know if "promise" is the right word, but I certainly have it in
my TODO list.

The grand plan (I was waiting until I had a patch to talk about this,
but since you asked...), looks something like this:

- Hookize FUNCTION_ARG &co.  (patch approved, I need to reassure myself
  that some of the const-ization in the patch isn't going to break
  bootstrap and commit)

- Hookize INIT_CUMULATIVE_ARGS &co.  INIT_CUMULATIVE_ARGS is the big
  one; I plan to convert it to something with prototype:

  CUMULATIVE_ARGS *target_init_cum_args (fntype, libname, fndecl, n_named);

  Other hooks (INIT_CUMULATIVE_INCOMING_ARGS, for instance) will be
  changed similarly to return a CUMULATIVE_ARGS *.  See below for
  discussion of problem with this approach.

- Convert all backends (big patch, but can be done incrementally.  I
  have private patches for the FUNCTION_ARG &co. hookization.)

- At this point, the non-backend portions of the compiler only deal with
  CUMULATIVE_ARGS through pointers; there are no direct references.

  It's possible there are other bits I am missing here, because I'm not
  familiar with this portion of the compiler.  Repeat above steps as
  necessary for hooks that I have failed to lookup and other bits.

- In one fell swoop, s/CUMULATIVE_ARGS/struct cumulative_args/ in the
  non-backend portions of the compiler.  Do the same in the backends,
  moving the actual definition of 'struct cumulative_args' into the
  backends's .c files, rather than the headers.

  This is one place where C++ and virtual functions would be useful; the
  target hooks dealing with CUMULATIVE_ARGS, I think, should really be
  methods on a CUMULATIVE_ARGS class.  (Depending on the target, this
  might enable removing some overhead with complicated argument passing
  that varies with the subarchitecture.)

There is one small problem with the above plan (that I am aware of;
perhaps there are others that I am not aware of, and I would welcome
pointers to them): what to do with managing the 'CUMULATIVE_ARGS *'
returned by the backend?  I think the options are:

- Have every backend return a pointer to statically allocated memory.
  This is the easiest thing to do, but also likely to blow up for weird
  uses of CUMULATIVE_ARGS.  No need to free or equivalent.  This is what
  I was going to do.

- Allocate it in the backend hook.  Presumably we want to dictate the
  method of allocation so we don't need to add *another* hook for
  deallocating.  obstacks, xmalloc, whatever.  I don't have an opinion
  here.

If people think something like the above plan is the way to go, it's not
clear to me that Joern's patch is a step forward, since
INCOMING_ARGS_INFO will just be bitrotten after the above plan lands on
trunk.

Comments?  Criticisms?  Bets on whether this can be done before the end
of stage 1? :)

-Nathan
Joern Rennecke - June 25, 2010, 3:16 a.m.
Quoting Nathan Froyd <froydnj@codesourcery.com>:

> The grand plan (I was waiting until I had a patch to talk about this,
> but since you asked...), looks something like this:
>
> - Hookize FUNCTION_ARG &co.  (patch approved, I need to reassure myself
>   that some of the const-ization in the patch isn't going to break
>   bootstrap and commit)
>
> - Hookize INIT_CUMULATIVE_ARGS &co.  INIT_CUMULATIVE_ARGS is the big
>   one; I plan to convert it to something with prototype:
>
>   CUMULATIVE_ARGS *target_init_cum_args (fntype, libname, fndecl, n_named);

This is wrong, because CUMULATIVE_ARGS is a target dependent type, so it makes
the target vector type useless to handle more than one target.
Either use a void* which is casted appropriately, or a pointer to a union.
You can see in multi-target-20100622-branch how multiple configured targets
can get separate union fields assigned.
The build machinery there creates the INCOMING_ARGS_INFO accessor macros.
The patch at the start of this thread contains the code for the case of
configuring for only a single target; this could be straightforwardly extended
to more macros if you want different names or ways to place the union tag.

>   This is one place where C++ and virtual functions would be useful; the
>   target hooks dealing with CUMULATIVE_ARGS, I think, should really be
>   methods on a CUMULATIVE_ARGS class.  (Depending on the target, this
>   might enable removing some overhead with complicated argument passing
>   that varies with the subarchitecture.)

But that would be a class that is different for every target, so again it is
not suitable to appear in the target hooks.
What you could do is to have a base class without class data, which has these
target methods, and then have the targets define target-specific derived
CUMULATIVE_ARGS classes, and have their target hooks expect that the pointers
point to an object of its own derived class.

> There is one small problem with the above plan (that I am aware of;
> perhaps there are others that I am not aware of, and I would welcome
> pointers to them): what to do with managing the 'CUMULATIVE_ARGS *'
> returned by the backend?  I think the options are:
>
> - Have every backend return a pointer to statically allocated memory.
>   This is the easiest thing to do, but also likely to blow up for weird
>   uses of CUMULATIVE_ARGS.  No need to free or equivalent.  This is what
>   I was going to do.

If we later want to go multi-threaded, that would have to become
thread-specific, i.e. often expensive.  The current scheme where the
caller allocates the memory is really better.  Typically the data is
wanted as a local variable on the stack.  And as I have demonstrated,
we can figure out the maximum amount of memory that any target's
CUMULATIVE_ARG needs, so that we can allocate a cumulative_args_u in the
caller.  Or for C++, when you create a base class for all CUMULATIVE_ARGS
types, you can have a member in cumulative_args_u which is of that type,
so that you can easily get a pointer to that.

> - Allocate it in the backend hook.  Presumably we want to dictate the
>   method of allocation so we don't need to add *another* hook for
>   deallocating.  obstacks, xmalloc, whatever.  I don't have an opinion
>   here.
>
> If people think something like the above plan is the way to go, it's not
> clear to me that Joern's patch is a step forward, since
> INCOMING_ARGS_INFO will just be bitrotten after the above plan lands on
> trunk.

INCOMING_ARGS_INFO is needed in lots of contexts:

E.g. in May last year I found this for the SH:

         * config/sh/sh.c (calc_live_regs): Use INCOMING_ARGS_INFO.
         (sh_expand_prologue, sh_expand_epilogue): Likewise.
         (sh_builtin_saveregs, sh_va_start): Likewise.
         (initial_elimination_offset, sh_allocate_initial_value): Likewise.
         (sh_function_ok_for_sibcall): Likewise.
         * config/sh/sh.md (return, return_i): Likewise.
         (shcompact_return_tramp, shcompact_return_tramp_i): Likewise.
Nathan Froyd - June 25, 2010, 11:27 a.m.
[Thread renamed like I should have done last night.  Whoops!]

On Thu, Jun 24, 2010 at 11:16:29PM -0400, Joern Rennecke wrote:
> Quoting Nathan Froyd <froydnj@codesourcery.com>:
>> - Hookize INIT_CUMULATIVE_ARGS &co.  INIT_CUMULATIVE_ARGS is the big
>>   one; I plan to convert it to something with prototype:
>>
>>   CUMULATIVE_ARGS *target_init_cum_args (fntype, libname, fndecl, n_named);
>
> This is wrong, because CUMULATIVE_ARGS is a target dependent type, so it makes
> the target vector type useless to handle more than one target.
> Either use a void* which is casted appropriately, or a pointer to a
> union.

I do not understand the relevance of this comment.  I agree that
CUMULATIVE_ARGS is a target dependent type.  The plan that I posted is
about removing the exposure of CUMULATIVE_ARGS to the non-backend
portions of the compiler.  The above step is one step along the way.  A
later step converts this returning of 'CUMULATIVE_ARGS *' to 'struct
cumulative_args *'; a forward declaration of 'struct cumulative_args'
can be provided in an appropriate header file.  If people are happier
with 'void *', that's fine too.  I was aiming for slightly
self-documenting code.

>>   This is one place where C++ and virtual functions would be useful; the
>>   target hooks dealing with CUMULATIVE_ARGS, I think, should really be
>>   methods on a CUMULATIVE_ARGS class.  (Depending on the target, this
>>   might enable removing some overhead with complicated argument passing
>>   that varies with the subarchitecture.)
>
> What you could do is to have a base class without class data, which has these
> target methods, and then have the targets define target-specific derived
> CUMULATIVE_ARGS classes, and have their target hooks expect that the pointers
> point to an object of its own derived class.

Yes, that was the plan.  My apologies if the intent was not clear.

>> There is one small problem with the above plan (that I am aware of;
>> perhaps there are others that I am not aware of, and I would welcome
>> pointers to them): what to do with managing the 'CUMULATIVE_ARGS *'
>> returned by the backend?  I think the options are:
>>
>> - Have every backend return a pointer to statically allocated memory.
>>   This is the easiest thing to do, but also likely to blow up for weird
>>   uses of CUMULATIVE_ARGS.  No need to free or equivalent.  This is what
>>   I was going to do.
>
> If we later want to go multi-threaded, that would have to become
> thread-specific, i.e. often expensive.

I think that a multi-threaded gcc is a *long* way off.  If we did ever
get to that point, one thread-specific variable and the cost of its
accesses would be the least of our problems.

-Nathan
Joern Rennecke - June 25, 2010, 12:30 p.m.
Quoting Nathan Froyd <froydnj@codesourcery.com>:

> I do not understand the relevance of this comment.  I agree that
> CUMULATIVE_ARGS is a target dependent type.  The plan that I posted is
> about removing the exposure of CUMULATIVE_ARGS to the non-backend
> portions of the compiler.

The problem is that when CUMULATIVE_ARGS becomes (more entrenched as)
part of the target hook interface, you'll have some 40 places for each
hook in the config files that need to be fixed to remove that
target-dependence from the target vector again.  That's a lot more work
than doing anything to the call site.

>  The above step is one step along the way.  A
> later step converts this returning of 'CUMULATIVE_ARGS *' to 'struct
> cumulative_args *'; a forward declaration of 'struct cumulative_args'
> can be provided in an appropriate header file.  If people are happier
> with 'void *', that's fine too.  I was aiming for slightly
> self-documenting code.

You can use a define or typedef to make that void * more self-documenting.
In fact I was thinking the other day that that's what I should do with
the enum reg_class -> int conversion too.
That should also make it easier if we later find a better way of doing
thing by some clever use of classes, or for register classes, if we get
to use any new language feature that allows to have an int for the interface
but treat it as passing / receiving an enum for type check purposes.

So if you do a
#define CUMULATIVE_ARGS_U CUMULATIVE_ARGS
and then use that in the target hook interface, and in the target hooks,
and cast between CUMULATIVE_ARGS_U * and CUMULATIVE_ARGS * as appropriate,
only the define would need to be changed to remove the target-dependency
from the target vector.

> I think that a multi-threaded gcc is a *long* way off.

I don't think it needs to be that far off.  So far, there was little demand
for it, because make -j works so well.  That will no longer be that case
with lto.  At the same time, we see the number of cores and available
simultaneously executed threads in workstation / server class machines
rising.  We might not want to care about all the details of handling
multithreading, but being able to apply some OMP directives to leverage
GOMP might already give some nice speedups, plus it's a matter of eating
our own dog food, so to speak.

> If we did ever
> get to that point, one thread-specific variable and the cost of its
> accesses would be the least of our problems.

I think it is important to keep future requirements in mind when we have
some choice when doing a design decision.  At the moment the cost of selecting
different paths is low; it's going to be much more expensive to switch later.

It's not the number of variables that matters so much as the number of
variable accesses during a compilation.  For typical C code (as compilation
workload for gcc) CUMULATIVE_ARGS accesses are probably not that important,
as we don't process function calls that often.  For C++ with lots of small
member functions I would expect that to be a little more.

But more importantly, once a particular way of doing things is established
in one place in GCC, it has a tendency to spread to other places where
analogous problems are encountered.
Nathan Froyd - June 25, 2010, 1:47 p.m.
On Fri, Jun 25, 2010 at 08:30:25AM -0400, Joern Rennecke wrote:
> Quoting Nathan Froyd <froydnj@codesourcery.com>:
>
>> I do not understand the relevance of this comment.  I agree that
>> CUMULATIVE_ARGS is a target dependent type.  The plan that I posted is
>> about removing the exposure of CUMULATIVE_ARGS to the non-backend
>> portions of the compiler.
>
> The problem is that when CUMULATIVE_ARGS becomes (more entrenched as)
> part of the target hook interface, you'll have some 40 places for each
> hook in the config files that need to be fixed to remove that
> target-dependence from the target vector again.  That's a lot more work
> than doing anything to the call site.

I don't understand the argument here.  How is moving around
CUMULATIVE_ARGS in the target hook interface making it "more
entrenched"?  Converting all references to CUMULATIVE_ARGS to use
pointers is actually making things less entrenched, because then the
layout of CUMULATIVE_ARGS need not be exposed to the non-backend
portions of the compiler.

>> I think that a multi-threaded gcc is a *long* way off.
>
> I don't think it needs to be that far off.  So far, there was little demand
> for it, because make -j works so well.  That will no longer be that case
> with lto.

WHOPR and friends effectively apply make -j to LTO compilations, so the
benefits of multi-threading go down substantially.

>> If we did ever
>> get to that point, one thread-specific variable and the cost of its
>> accesses would be the least of our problems.
>
> It's not the number of variables that matters so much as the number of
> variable accesses during a compilation.  For typical C code (as compilation
> workload for gcc) CUMULATIVE_ARGS accesses are probably not that important,
> as we don't process function calls that often.  For C++ with lots of small
> member functions I would expect that to be a little more.

The accesses we are talking about here are the cost of computing the
address of the thread-local variable once in the
TARGET_INIT_CUMULATIVE_ARGS hook.  Before multi-threading:

static void *
ix86_init_cumulative_args (blah_blah)
{
  static struct ix86_cumulative_args ca;

  /* init CA */

  return &ca;
}

After multi-threading:

static void *
ix86_init_cumulative_args (blah_blah)
{
  static __thread struct ix86_cumulative_args ca;
  /* I don't know if the compiler is able to optimize:

     ca.foo = x;
     ca.bar = y;

     to compute the address of CA only once.  If so, this bit could go
     away.  */
  struct ix86_cumulative_args *pca = &ca;

  /* init PCA */

  return pca;
}

Doing this is not particularly expensive, even if computing the address
requires several thousand cycles.  Querying and setting members of PCA,
as would happen in other target hooks, runs at full speed.  All those
small members functions are likely to get inlined anyway, so we'll never
generate out-of-line code for them.

-Nathan
Joern Rennecke - June 25, 2010, 2:15 p.m.
Quoting Nathan Froyd <froydnj@codesourcery.com>:

> I don't understand the argument here.  How is moving around
> CUMULATIVE_ARGS in the target hook interface making it "more
> entrenched"?  Converting all references to CUMULATIVE_ARGS to use
> pointers is actually making things less entrenched, because then the
> layout of CUMULATIVE_ARGS need not be exposed to the non-backend
> portions of the compiler.

That's a misunderstanding then.  No, changing from CUMULATIVE_ARGS to
CUMULATIVE_ARGS * does not create any new problems (as long as you don't
have any arrays / pointer-arithmetic (e.g. increment) on these pointers).
I meant you increase the problem when you increase the number of target
hooks that use CUMULATIVE_ARGS, or increase the number of their
implementations in the various config/*/* files.
Nathan Froyd - June 25, 2010, 5:27 p.m.
On Fri, Jun 25, 2010 at 10:15:39AM -0400, Joern Rennecke wrote:
> Quoting Nathan Froyd <froydnj@codesourcery.com>:
>
>> I don't understand the argument here.  How is moving around
>> CUMULATIVE_ARGS in the target hook interface making it "more
>> entrenched"?  Converting all references to CUMULATIVE_ARGS to use
>> pointers is actually making things less entrenched, because then the
>> layout of CUMULATIVE_ARGS need not be exposed to the non-backend
>> portions of the compiler.
>
> That's a misunderstanding then.  No, changing from CUMULATIVE_ARGS to
> CUMULATIVE_ARGS * does not create any new problems (as long as you don't
> have any arrays / pointer-arithmetic (e.g. increment) on these pointers).
> I meant you increase the problem when you increase the number of target
> hooks that use CUMULATIVE_ARGS, or increase the number of their
> implementations in the various config/*/* files.

But you're not increasing the number of points that use CUMULATIVE_ARGS.
If you have a target macro that uses CUMULATIVE_ARGS, and you change
that to a target hook that uses CUMULATIVE_ARGS *, you haven't changed
the number of points in the backend that deal with it.  I don't see how
moving the implementation of CUMULATIVE_ARGS-using bits from
config/$ARCH/$ARCH.h to config/$ARCH/$ARCH.c is contributing to further
entrenchment.  It's making things better because of the above layout
concern and because you don't have random backend bits being stuck into
the middle-end via macros.

-Nathan
Joern Rennecke - June 25, 2010, 5:37 p.m.
Quoting Nathan Froyd <froydnj@codesourcery.com>:

> But you're not increasing the number of points that use CUMULATIVE_ARGS.
> If you have a target macro that uses CUMULATIVE_ARGS, and you change
> that to a target hook that uses CUMULATIVE_ARGS *, you haven't changed
> the number of points in the backend that deal with it.  I don't see how
> moving the implementation of CUMULATIVE_ARGS-using bits from
> config/$ARCH/$ARCH.h to config/$ARCH/$ARCH.c is contributing to further
> entrenchment.

targhooks.c is compiled once for every target.  But I have to change its
source code only once to change the interface, no matter what target
macros it uses inside.  Likewise, other code in the compiler that depends
on target macros gets compiled separately for each target.

The target vector is supposed to isulate the middle-end from target
dependencies; if its interface becomes target-dependent, that makes
it useless for that purpose.
Nathan Froyd - June 25, 2010, 5:55 p.m.
On Fri, Jun 25, 2010 at 01:37:21PM -0400, Joern Rennecke wrote:
> targhooks.c is compiled once for every target.  But I have to change its
> source code only once to change the interface, no matter what target
> macros it uses inside.  Likewise, other code in the compiler that depends
> on target macros gets compiled separately for each target.
>
> The target vector is supposed to isulate the middle-end from target
> dependencies; if its interface becomes target-dependent, that makes
> it useless for that purpose.

Yes, we agree here, but I must be dense, because I can't tell what
changes that you think I would make that make it target-dependent.
Could you please provide examples of such changes?  Just for
clarification: I'm talking about making hooks that take/return pointers
to CUMULATIVE_ARGS, *not* the actual CUMULATIVE_ARGS structure.

-Nathan
Joern Rennecke - June 25, 2010, 6:05 p.m.
Quoting Nathan Froyd <froydnj@codesourcery.com>:

> Yes, we agree here, but I must be dense, because I can't tell what
> changes that you think I would make that make it target-dependent.
> Could you please provide examples of such changes?  Just for
> clarification: I'm talking about making hooks that take/return pointers
> to CUMULATIVE_ARGS, *not* the actual CUMULATIVE_ARGS structure.

If you declare it as CUMULATIVE_ARGS *, then alias analysis is entitled to
think that this can't be anything but the CUMULATIVE_ARGS that it is
currently seeing.  A compiler is even entitled to have different kinds  
of pointers dependent on the data type pointed to - although gcc  
doesn't do
this (for now?).

If you declare it as void * - or something typedef'ed to void * - than this
problem does not arise.
Nathan Froyd - June 25, 2010, 6:16 p.m.
On Fri, Jun 25, 2010 at 02:05:26PM -0400, Joern Rennecke wrote:
> Quoting Nathan Froyd <froydnj@codesourcery.com>:
>> Yes, we agree here, but I must be dense, because I can't tell what
>> changes that you think I would make that make it target-dependent.
>> Could you please provide examples of such changes?  Just for
>> clarification: I'm talking about making hooks that take/return pointers
>> to CUMULATIVE_ARGS, *not* the actual CUMULATIVE_ARGS structure.
>
> If you declare it as void * - or something typedef'ed to void * - than this
> problem does not arise.

OK, great.  This can be done after (or concurrently with) the last step
of the grand plan posted above.  I don't think it's worth doing
something with 'void *' until things are hookized appropriately.  Once
the hookization is complete, I agree that it would be reasonable to use
'void *' or similar to ensure the compiler does not perform unexpected
optimizations and to guard against errant pointer arithmetic.

-Nathan
Joern Rennecke - June 25, 2010, 7:20 p.m.
Quoting Joern Rennecke <amylaar@spamcop.net>:

+        ) >> tmp-target-gtypes.h

That was supposed to read '>'.

Likewise in the patch for RTL_ASM_CLOBBERS, except that when you reassemble
the pieces again, it goes back to '>>'.
Joern Rennecke - Dec. 17, 2010, 11:43 a.m.
Quoting Nathan Froyd <froydnj@codesourcery.com>:

> The grand plan (I was waiting until I had a patch to talk about this,
> but since you asked...), looks something like this:
>
> - Hookize FUNCTION_ARG &co.  (patch approved, I need to reassure myself
>   that some of the const-ization in the patch isn't going to break
>   bootstrap and commit)
>
> - Hookize INIT_CUMULATIVE_ARGS &co.  INIT_CUMULATIVE_ARGS is the big
>   one; I plan to convert it to something with prototype:
>
>   CUMULATIVE_ARGS *target_init_cum_args (fntype, libname, fndecl, n_named);

As has been discussed in the meantime, we need a target-independent, opaque
type for the hook interface, which can be cumulative_args_t, typedefed to a
struct or union pointer, and converted from/to the target specific type in
a pair of small inline functions.
>
>   Other hooks (INIT_CUMULATIVE_INCOMING_ARGS, for instance) will be
>   changed similarly to return a CUMULATIVE_ARGS *.  See below for
>   discussion of problem with this approach.
>
> - Convert all backends (big patch, but can be done incrementally.  I
>   have private patches for the FUNCTION_ARG &co. hookization.)
>
> - At this point, the non-backend portions of the compiler only deal with
>   CUMULATIVE_ARGS through pointers; there are no direct references.
>
>   It's possible there are other bits I am missing here, because I'm not
>   familiar with this portion of the compiler.  Repeat above steps as
>   necessary for hooks that I have failed to lookup and other bits.
>
> - In one fell swoop, s/CUMULATIVE_ARGS/struct cumulative_args/ in the
>   non-backend portions of the compiler.  Do the same in the backends,
>   moving the actual definition of 'struct cumulative_args' into the
>   backends's .c files, rather than the headers.
>
>   This is one place where C++ and virtual functions would be useful; the
>   target hooks dealing with CUMULATIVE_ARGS, I think, should really be
>   methods on a CUMULATIVE_ARGS class.  (Depending on the target, this
>   might enable removing some overhead with complicated argument passing
>   that varies with the subarchitecture.)
>
> There is one small problem with the above plan (that I am aware of;
> perhaps there are others that I am not aware of, and I would welcome
> pointers to them): what to do with managing the 'CUMULATIVE_ARGS *'
> returned by the backend?  I think the options are:
>
> - Have every backend return a pointer to statically allocated memory.
>   This is the easiest thing to do, but also likely to blow up for weird
>   uses of CUMULATIVE_ARGS.  No need to free or equivalent.  This is what
>   I was going to do.

That will be most efficient for the majority us uses, and thus should be
supported.
>
> - Allocate it in the backend hook.  Presumably we want to dictate the
>   method of allocation so we don't need to add *another* hook for
>   deallocating.  obstacks, xmalloc, whatever.  I don't have an opinion
>   here.

The problem is that that this doesn't allow you to use even alloca, so
you'd need a high-overhead allocation function.

I think it is better to have a piece-of-data target "hook" for the size
to allocate for a cumulative_args_t.
Then the init_cumulative_args hook takes a void * argument for the  allocated
memory.  Targets that are fine with the statically allocated scheme can
pass in NULL.
>
> If people think something like the above plan is the way to go, it's not
> clear to me that Joern's patch is a step forward, since
> INCOMING_ARGS_INFO will just be bitrotten after the above plan lands on
> trunk.
>
> Comments?  Criticisms?  Bets on whether this can be done before the end
> of stage 1? :)
>
> -Nathan
>

Patch

Index: gcc/target.h
===================================================================
--- gcc/target.h	(revision 161310)
+++ gcc/target.h	(working copy)
@@ -976,6 +976,10 @@  struct gcc_target
     bool (*return_in_memory) (const_tree type, const_tree fndecl);
     bool (*return_in_msb) (const_tree type);
 
+    /* ??? FIXME: we shouldn't use CUMULATIVE_ARGS in the target hook
+       interface, here, because this is a target dependent type.
+       We should use union cumulative_args_u instead.  */
+
     /* Return true if a parameter must be passed by reference.  TYPE may
        be null if this is a libcall.  CA may be null if this query is
        from __builtin_va_arg.  */
Index: gcc/function.c
===================================================================
--- gcc/function.c	(revision 161310)
+++ gcc/function.c	(working copy)
@@ -3375,7 +3375,7 @@  assign_parms (tree fndecl)
   /* For stdarg.h function, save info about
      regs and stack space used by the named args.  */
 
-  crtl->args.info = all.args_so_far;
+  INCOMING_ARGS_INFO (crtl->args) = all.args_so_far;
 
   /* Set the rtx used for the function return value.  Put this in its
      own variable so any optimizers that need this information don't have
Index: gcc/function.h
===================================================================
--- gcc/function.h	(revision 161310)
+++ gcc/function.h	(working copy)
@@ -27,6 +27,7 @@  along with GCC; see the file COPYING3.  
 #include "vecprim.h"
 #include "tm.h"		/* For CUMULATIVE_ARGS.  */
 #include "hard-reg-set.h"
+#include "target-gtypes.h"
 
 /* Stack of pending (incomplete) sequences saved by `start_sequence'.
    Each element describes one pending sequence.
@@ -210,12 +211,14 @@  struct GTY(()) incoming_args {
 
   /* Quantities of various kinds of registers
      used for the current function's args.  */
-  CUMULATIVE_ARGS info;
+  cumulative_args_u GTY ((desc ("cfun ? cfun->target_arch : -1"))) info;
 
   /* The arg pointer hard register, or the pseudo into which it was copied.  */
   rtx internal_arg_pointer;
 };
 
+#define INCOMING_ARGS_INFO(INCOMING_ARGS) ((INCOMING_ARGS).info._ca)
+
 /* Data for function partitioning.  */
 struct GTY(()) function_subsections {
   /* Assembly labels for the hot and cold text sections, to
@@ -607,6 +610,9 @@  struct GTY(()) function {
      adjusts one of its arguments and forwards to another
      function.  */
   unsigned int is_thunk : 1;
+
+  /* Target architecture to compile this function for.  */
+  unsigned int target_arch : 8;
 };
 
 /* If va_list_[gf]pr_size is set to this, it means we don't know how
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 161310)
+++ gcc/Makefile.in	(working copy)
@@ -800,6 +800,9 @@  T =
 T_TARGET =
 T_TARGET : $(T_TARGET)
 
+# For building rtl pases for extra target architectures.
+TARGET_NUM=0
+
 # This should name the specs file that we're going to install.  Target
 # Makefiles may override it and name another file to be generated from
 # the built-in specs and installed as the default spec, as long as
@@ -1668,7 +1671,9 @@  cs-tconfig.h: Makefile
 
 cs-tm.h: Makefile
 	TARGET_CPU_DEFAULT="$(target_cpu_default)" \
-	HEADERS="$(tm_include_list)" DEFINES="$(tm_defines)" \
+	HEADERS="$(tm_include_list)" \
+	DEFINES="TARGET_NUM=$(TARGET_NUM) \
+	$(tm_defines)" \
 	$(SHELL) $(srcdir)/mkconfig.sh tm.h
 
 cs-tm_p.h: Makefile
@@ -3671,7 +3676,7 @@  s-constrs-h: $(MD_DEPS) build/genpreds$(
 
 GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/vecprim.h $(srcdir)/vecir.h \
-  $(host_xm_file_list) \
+  $(host_xm_file_list) target-gtypes.h \
   $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) $(srcdir)/bitmap.h \
   $(srcdir)/alias.h $(srcdir)/coverage.c $(srcdir)/rtl.h \
   $(srcdir)/optabs.h $(srcdir)/tree.h $(srcdir)/libfuncs.h $(SYMTAB_H) \
@@ -3848,6 +3853,17 @@  build/genpreds.o : genpreds.c $(RTL_BASE
 build/genrecog.o : genrecog.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
   coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
 
+target-gtypes.h: s-target-gtypes; @true
+# using struct instead of union makes this gty-safe.
+s-target-gtypes: Makefile
+	(echo 'typedef union GTY (())'; \
+	 echo '  {'; \
+	 echo '    CUMULATIVE_ARGS GTY ((tag ("TARGET_NUM"))) _ca;'; \
+	 echo '  } cumulative_args_u;'; \
+	) >> tmp-target-gtypes.h
+	$(SHELL) $(srcdir)/../move-if-change tmp-target-gtypes.h target-gtypes.h
+	$(STAMP) s-target-gtypes
+
 # Compile the programs that generate insn-* from the machine description.
 # They are compiled with $(COMPILER_FOR_BUILD), and associated libraries,
 # since they need to run on this machine
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	(revision 161310)
+++ gcc/config/alpha/alpha.c	(working copy)
@@ -185,9 +185,9 @@  static struct alpha_rtx_cost_data const 
 
 /* Get the number of args of a function in one of two ways.  */
 #if TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK
-#define NUM_ARGS crtl->args.info.num_args
+#define NUM_ARGS INCOMING_ARGS_INFO (crtl->args).num_args
 #else
-#define NUM_ARGS crtl->args.info
+#define NUM_ARGS INCOMING_ARGS_INFO (crtl->args)
 #endif
 
 #define REG_PV 27
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	(revision 161310)
+++ gcc/config/frv/frv.c	(working copy)
@@ -2251,7 +2251,8 @@  static void
 frv_expand_builtin_va_start (tree valist, rtx nextarg)
 {
   tree t;
-  int num = crtl->args.info - FIRST_ARG_REGNUM - FRV_NUM_ARG_REGS;
+  int num
+    = INCOMING_ARGS_INFO (crtl->args) - FIRST_ARG_REGNUM - FRV_NUM_ARG_REGS;
 
   nextarg = gen_rtx_PLUS (Pmode, virtual_incoming_args_rtx,
 			  GEN_INT (UNITS_PER_WORD * num));
@@ -2259,7 +2260,7 @@  frv_expand_builtin_va_start (tree valist
   if (TARGET_DEBUG_ARG)
     {
       fprintf (stderr, "va_start: args_info = %d, num = %d\n",
-	       crtl->args.info, num);
+	       INCOMING_ARGS_INFO (crtl->args), num);
 
       debug_rtx (nextarg);
     }
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	(revision 161310)
+++ gcc/config/s390/s390.c	(working copy)
@@ -7113,9 +7113,9 @@  s390_register_info (int clobbered_regs[]
     {
       /* Varargs functions need to save gprs 2 to 6.  */
       if (cfun->va_list_gpr_size
-	  && crtl->args.info.gprs < GP_ARG_NUM_REG)
+	  && INCOMING_ARGS_INFO (crtl->args).gprs < GP_ARG_NUM_REG)
 	{
-	  int min_gpr = crtl->args.info.gprs;
+	  int min_gpr = INCOMING_ARGS_INFO (crtl->args).gprs;
 	  int max_gpr = min_gpr + cfun->va_list_gpr_size;
 	  if (max_gpr > GP_ARG_NUM_REG)
 	    max_gpr = GP_ARG_NUM_REG;
@@ -7137,9 +7137,9 @@  s390_register_info (int clobbered_regs[]
 
       /* Mark f0, f2 for 31 bit and f0-f4 for 64 bit to be saved.  */
       if (TARGET_HARD_FLOAT && cfun->va_list_fpr_size
-	  && crtl->args.info.fprs < FP_ARG_NUM_REG)
+	  && INCOMING_ARGS_INFO (crtl->args).fprs < FP_ARG_NUM_REG)
 	{
-	  int min_fpr = crtl->args.info.fprs;
+	  int min_fpr = INCOMING_ARGS_INFO (crtl->args).fprs;
 	  int max_fpr = min_fpr + cfun->va_list_fpr_size;
 	  if (max_fpr > FP_ARG_NUM_REG)
 	    max_fpr = FP_ARG_NUM_REG;
@@ -8604,7 +8604,7 @@  s390_build_builtin_va_list (void)
    The following global variables are used to initialize
    the va_list structure:
 
-     crtl->args.info:
+     INCOMING_ARGS_INFO (crtl->args):
        holds number of gprs and fprs used for named arguments.
      crtl->args.arg_offset_rtx:
        holds the offset of the first anonymous stack argument
@@ -8631,8 +8631,8 @@  s390_va_start (tree valist, rtx nextarg 
 
   /* Count number of gp and fp argument registers used.  */
 
-  n_gpr = crtl->args.info.gprs;
-  n_fpr = crtl->args.info.fprs;
+  n_gpr = INCOMING_ARGS_INFO (crtl->args).gprs;
+  n_fpr = INCOMING_ARGS_INFO (crtl->args).fprs;
 
   if (cfun->va_list_gpr_size)
     {
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	(revision 161310)
+++ gcc/config/spu/spu.c	(working copy)
@@ -4100,7 +4100,7 @@  spu_build_builtin_va_list (void)
    The following global variables are used to initialize
    the va_list structure:
 
-     crtl->args.info;
+     INCOMING_ARGS_INFO (crtl->args);
        the CUMULATIVE_ARGS for this function
 
      crtl->args.arg_offset_rtx:
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	(revision 161310)
+++ gcc/config/sparc/sparc.c	(working copy)
@@ -5890,7 +5890,7 @@  sparc_function_value_regno_p (const unsi
 static rtx
 sparc_builtin_saveregs (void)
 {
-  int first_reg = crtl->args.info.words;
+  int first_reg = INCOMING_ARGS_INFO (crtl->args).words;
   rtx address;
   int regno;
 
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 161310)
+++ gcc/config/i386/i386.c	(working copy)
@@ -7058,9 +7058,9 @@  ix86_va_start (tree valist, rtx nextarg)
   sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
 
   /* Count number of gp and fp argument registers used.  */
-  words = crtl->args.info.words;
-  n_gpr = crtl->args.info.regno;
-  n_fpr = crtl->args.info.sse_regno;
+  words = INCOMING_ARGS_INFO (crtl->args).words;
+  n_gpr = INCOMING_ARGS_INFO (crtl->args).regno;
+  n_fpr = INCOMING_ARGS_INFO (crtl->args).sse_regno;
 
   if (cfun->va_list_gpr_size)
     {
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	(revision 161310)
+++ gcc/config/sh/sh.c	(working copy)
@@ -6519,7 +6519,7 @@  calc_live_regs (HARD_REG_SET *live_regs_
   /* Force PR to be live if the prologue has to call the SHmedia
      argument decoder or register saver.  */
   if (TARGET_SHCOMPACT
-      && ((crtl->args.info.call_cookie
+      && ((INCOMING_ARGS_INFO (crtl->args).call_cookie
 	   & ~ CALL_COOKIE_RET_TRAMP (1))
 	  || crtl->saves_all_registers))
     pr_live = 1;
@@ -6546,7 +6546,7 @@  calc_live_regs (HARD_REG_SET *live_regs_
 	  : (/* Only push those regs which are used and need to be saved.  */
 	     (TARGET_SHCOMPACT
 	      && flag_pic
-	      && crtl->args.info.call_cookie
+	      && INCOMING_ARGS_INFO (crtl->args).call_cookie
 	      && reg == PIC_OFFSET_TABLE_REGNUM)
 	     || (df_regs_ever_live_p (reg)
 		 && ((!call_really_used_regs[reg]
@@ -6802,14 +6802,15 @@  sh_expand_prologue (void)
   pretend_args = crtl->args.pretend_args_size;
   if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl)
       && (NPARM_REGS(SImode)
-	  > crtl->args.info.arg_count[(int) SH_ARG_INT]))
+	  > INCOMING_ARGS_INFO (crtl->args).arg_count[(int) SH_ARG_INT]))
     pretend_args = 0;
   /* Dwarf2 module doesn't expect frame related insns here.  */
   output_stack_adjust (-pretend_args
-		       - crtl->args.info.stack_regs * 8,
+		       - INCOMING_ARGS_INFO (crtl->args).stack_regs * 8,
 		       stack_pointer_rtx, 0, NULL, false);
 
-  if (TARGET_SHCOMPACT && flag_pic && crtl->args.info.call_cookie)
+  if (TARGET_SHCOMPACT && flag_pic
+      && INCOMING_ARGS_INFO (crtl->args).call_cookie)
     /* We're going to use the PIC register to load the address of the
        incoming-argument decoder and/or of the return trampoline from
        the GOT, so make sure the PIC register is preserved and
@@ -6817,7 +6818,8 @@  sh_expand_prologue (void)
     df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
 
   if (TARGET_SHCOMPACT
-      && (crtl->args.info.call_cookie & ~ CALL_COOKIE_RET_TRAMP(1)))
+      && (INCOMING_ARGS_INFO (crtl->args).call_cookie
+	  & ~ CALL_COOKIE_RET_TRAMP(1)))
     {
       int reg;
 
@@ -6825,20 +6827,21 @@  sh_expand_prologue (void)
 	 be pushed onto the stack live, so that register renaming
 	 doesn't overwrite them.  */
       for (reg = 0; reg < NPARM_REGS (SImode); reg++)
-	if (CALL_COOKIE_STACKSEQ_GET (crtl->args.info.call_cookie)
+	if ((CALL_COOKIE_STACKSEQ_GET
+	     (INCOMING_ARGS_INFO (crtl->args).call_cookie))
 	    >= NPARM_REGS (SImode) - reg)
 	  for (; reg < NPARM_REGS (SImode); reg++)
 	    emit_insn (gen_shcompact_preserve_incoming_args
 		       (gen_rtx_REG (SImode, FIRST_PARM_REG + reg)));
 	else if (CALL_COOKIE_INT_REG_GET
-		 (crtl->args.info.call_cookie, reg) == 1)
+		 (INCOMING_ARGS_INFO (crtl->args).call_cookie, reg) == 1)
 	  emit_insn (gen_shcompact_preserve_incoming_args
 		     (gen_rtx_REG (SImode, FIRST_PARM_REG + reg)));
 
       emit_move_insn (gen_rtx_REG (Pmode, MACL_REG),
 		      stack_pointer_rtx);
       emit_move_insn (gen_rtx_REG (SImode, R0_REG),
-		      GEN_INT (crtl->args.info.call_cookie));
+		      GEN_INT (INCOMING_ARGS_INFO (crtl->args).call_cookie));
       emit_move_insn (gen_rtx_REG (SImode, MACH_REG),
 		      gen_rtx_REG (SImode, R0_REG));
     }
@@ -6863,7 +6866,8 @@  sh_expand_prologue (void)
 	      rtx insn;
 
 	      if (i >= (NPARM_REGS(SImode)
-			- crtl->args.info.arg_count[(int) SH_ARG_INT]
+			- (INCOMING_ARGS_INFO
+			   (crtl->args).arg_count[(int) SH_ARG_INT])
 			))
 		break;
 	      insn = push (rn);
@@ -7119,7 +7123,8 @@  sh_expand_prologue (void)
     frame_insn (GEN_MOV (hard_frame_pointer_rtx, stack_pointer_rtx));
 
   if (TARGET_SHCOMPACT
-      && (crtl->args.info.call_cookie & ~ CALL_COOKIE_RET_TRAMP(1)))
+      && (INCOMING_ARGS_INFO (crtl->args).call_cookie
+	  & ~ CALL_COOKIE_RET_TRAMP(1)))
     {
       /* This must NOT go through the PLT, otherwise mach and macl
 	 may be clobbered.  */
@@ -7381,7 +7386,7 @@  sh_expand_epilogue (bool sibcall_p)
 
   output_stack_adjust (crtl->args.pretend_args_size
 		       + save_size + d_rounding
-		       + crtl->args.info.stack_regs * 8,
+		       + INCOMING_ARGS_INFO (crtl->args).stack_regs * 8,
 		       stack_pointer_rtx, e, NULL, false);
 
   if (crtl->calls_eh_return)
@@ -7504,11 +7509,13 @@  static rtx
 sh_builtin_saveregs (void)
 {
   /* First unnamed integer register.  */
-  int first_intreg = crtl->args.info.arg_count[(int) SH_ARG_INT];
+  int first_intreg
+    = INCOMING_ARGS_INFO (crtl->args).arg_count[(int) SH_ARG_INT];
   /* Number of integer registers we need to save.  */
   int n_intregs = MAX (0, NPARM_REGS (SImode) - first_intreg);
   /* First unnamed SFmode float reg */
-  int first_floatreg = crtl->args.info.arg_count[(int) SH_ARG_FLOAT];
+  int first_floatreg
+    = INCOMING_ARGS_INFO (crtl->args).arg_count[(int) SH_ARG_FLOAT];
   /* Number of SFmode float regs to save.  */
   int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg);
   rtx regbuf, fpregs;
@@ -7523,22 +7530,22 @@  sh_builtin_saveregs (void)
 
 	  while (pushregs < NPARM_REGS (SImode) - 1
 		 && (CALL_COOKIE_INT_REG_GET
-			(crtl->args.info.call_cookie,
+			(INCOMING_ARGS_INFO (crtl->args).call_cookie,
 			 NPARM_REGS (SImode) - pushregs)
 		     == 1))
 	    {
-	      crtl->args.info.call_cookie
+	      INCOMING_ARGS_INFO (crtl->args).call_cookie
 		&= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode)
 					  - pushregs, 1);
 	      pushregs++;
 	    }
 
 	  if (pushregs == NPARM_REGS (SImode))
-	    crtl->args.info.call_cookie
+	    INCOMING_ARGS_INFO (crtl->args).call_cookie
 	      |= (CALL_COOKIE_INT_REG (0, 1)
 		  | CALL_COOKIE_STACKSEQ (pushregs - 1));
 	  else
-	    crtl->args.info.call_cookie
+	    INCOMING_ARGS_INFO (crtl->args).call_cookie
 	      |= CALL_COOKIE_STACKSEQ (pushregs);
 
 	  crtl->args.pretend_args_size += 8 * n_intregs;
@@ -7748,7 +7755,7 @@  sh_va_start (tree valist, rtx nextarg)
   TREE_SIDE_EFFECTS (t) = 1;
   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
 
-  nfp = crtl->args.info.arg_count[SH_ARG_FLOAT];
+  nfp = INCOMING_ARGS_INFO (crtl->args).arg_count[SH_ARG_FLOAT];
   if (nfp < 8)
     nfp = 8 - nfp;
   else
@@ -7763,7 +7770,7 @@  sh_va_start (tree valist, rtx nextarg)
   TREE_SIDE_EFFECTS (t) = 1;
   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
 
-  nint = crtl->args.info.arg_count[SH_ARG_INT];
+  nint = INCOMING_ARGS_INFO (crtl->args).arg_count[SH_ARG_INT];
   if (nint < 4)
     nint = 4 - nint;
   else
@@ -8550,11 +8557,11 @@  initial_elimination_offset (int from, in
 
   if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
     return total_saved_regs_space + total_auto_space
-      + crtl->args.info.byref_regs * 8;
+      + INCOMING_ARGS_INFO (crtl->args).byref_regs * 8;
 
   if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
     return total_saved_regs_space + total_auto_space
-      + crtl->args.info.byref_regs * 8;
+      + INCOMING_ARGS_INFO (crtl->args).byref_regs * 8;
 
   /* Initial gap between fp and sp is 0.  */
   if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
@@ -10126,7 +10133,7 @@  sh_allocate_initial_value (rtx hard_reg)
       if (current_function_is_leaf
 	  && ! sh_pr_n_sets ()
 	  && ! (TARGET_SHCOMPACT
-		&& ((crtl->args.info.call_cookie
+		&& ((INCOMING_ARGS_INFO (crtl->args).call_cookie
 		     & ~ CALL_COOKIE_RET_TRAMP (1))
 		    || crtl->saves_all_registers)))
 	x = hard_reg;
@@ -10736,7 +10743,7 @@  sh_function_ok_for_sibcall (tree decl, t
 {
   return (1
 	  && (! TARGET_SHCOMPACT
-	      || crtl->args.info.stack_regs == 0)
+	      || INCOMING_ARGS_INFO (crtl->args).stack_regs == 0)
 	  && ! sh_cfun_interrupt_handler_p ()
 	  && (! flag_pic
 	      || (decl && ! TREE_PUBLIC (decl))
@@ -11651,7 +11658,7 @@  sh_get_pr_initial_val (void)
      PR register on SHcompact, because it might be clobbered by the prologue.
      We check first if that is known to be the case.  */
   if (TARGET_SHCOMPACT
-      && ((crtl->args.info.call_cookie
+      && ((INCOMING_ARGS_INFO (crtl->args).call_cookie
 	   & ~ CALL_COOKIE_RET_TRAMP (1))
 	  || crtl->saves_all_registers))
     return gen_frame_mem (SImode, return_address_pointer_rtx);
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md	(revision 161310)
+++ gcc/config/sh/sh.md	(working copy)
@@ -9018,7 +9018,8 @@  (define_expand "return"
     }
 
   if (TARGET_SHCOMPACT
-      && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
+      && (INCOMING_ARGS_INFO (crtl->args).call_cookie
+	  & CALL_COOKIE_RET_TRAMP (1)))
     {
       emit_jump_insn (gen_shcompact_return_tramp ());
       DONE;
@@ -9028,7 +9029,7 @@  (define_expand "return"
 (define_insn "*return_i"
   [(return)]
   "TARGET_SH1 && ! (TARGET_SHCOMPACT
-		    && (crtl->args.info.call_cookie
+		    && (INCOMING_ARGS_INFO (crtl->args).call_cookie
 			& CALL_COOKIE_RET_TRAMP (1)))
    && reload_completed
    && lookup_attribute (\"trap_exit\",
@@ -9055,7 +9056,7 @@  (define_insn "*return_trapa"
 (define_expand "shcompact_return_tramp"
   [(return)]
   "TARGET_SHCOMPACT
-   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
+   && (INCOMING_ARGS_INFO (crtl->args).call_cookie & CALL_COOKIE_RET_TRAMP (1))"
   "
 {
   rtx reg = gen_rtx_REG (Pmode, R0_REG);
@@ -9068,7 +9069,7 @@  (define_expand "shcompact_return_tramp"
 (define_insn "shcompact_return_tramp_i"
   [(parallel [(return) (use (reg:SI R0_REG))])]
   "TARGET_SHCOMPACT
-   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
+   && (INCOMING_ARGS_INFO (crtl->args).call_cookie & CALL_COOKIE_RET_TRAMP (1))"
   "jmp	@r0%#"
   [(set_attr "type" "jump_ind")
    (set_attr "needs_delay_slot" "yes")])
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c	(revision 161310)
+++ gcc/config/avr/avr.c	(working copy)
@@ -2748,7 +2748,7 @@  bool
 avr_frame_pointer_required_p (void)
 {
   return (cfun->calls_alloca
-	  || crtl->args.info.nregs == 0
+	  || INCOMING_ARGS_INFO (crtl->args).nregs == 0
   	  || get_frame_size () > 0);
 }
 
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	(revision 161310)
+++ gcc/config/xtensa/xtensa.c	(working copy)
@@ -2699,7 +2699,7 @@  static rtx
 xtensa_builtin_saveregs (void)
 {
   rtx gp_regs;
-  int arg_words = crtl->args.info.arg_words;
+  int arg_words = INCOMING_ARGS_INFO (crtl->args).arg_words;
   int gp_left = MAX_ARGS_IN_REGISTERS - arg_words;
 
   if (gp_left <= 0)
@@ -2736,7 +2736,7 @@  xtensa_va_start (tree valist, rtx nextar
   tree t, u;
   int arg_words;
 
-  arg_words = crtl->args.info.arg_words;
+  arg_words = INCOMING_ARGS_INFO (crtl->args).arg_words;
 
   f_stk = TYPE_FIELDS (va_list_type_node);
   f_reg = TREE_CHAIN (f_stk);
@@ -3131,7 +3131,7 @@  order_regs_for_local_alloc (void)
 
       /* Use the AR registers in increasing order (skipping a0 and a1)
 	 but save the incoming argument registers for a last resort.  */
-      num_arg_regs = crtl->args.info.arg_words;
+      num_arg_regs = INCOMING_ARGS_INFO (crtl->args).arg_words;
       if (num_arg_regs > MAX_ARGS_IN_REGISTERS)
 	num_arg_regs = MAX_ARGS_IN_REGISTERS;
       for (i = GP_ARG_FIRST; i < 16 - num_arg_regs; i++)
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c	(revision 161310)
+++ gcc/config/stormy16/stormy16.c	(working copy)
@@ -1355,7 +1355,7 @@  xstormy16_expand_builtin_va_start (tree 
 
   t = build2 (MODIFY_EXPR, TREE_TYPE (count), count,
 	      build_int_cst (NULL_TREE,
-			     crtl->args.info * UNITS_PER_WORD));
+			     INCOMING_ARGS_INFO (crtl->args) * UNITS_PER_WORD));
   TREE_SIDE_EFFECTS (t) = 1;
   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
 }
Index: gcc/config/m68hc11/m68hc11.c
===================================================================
--- gcc/config/m68hc11/m68hc11.c	(revision 161310)
+++ gcc/config/m68hc11/m68hc11.c	(working copy)
@@ -1617,7 +1617,7 @@  expand_prologue (void)
      If the first argument is a 32-bit quantity, the D+X registers
      are used.  Use Y to compute the frame.  Otherwise, X is cheaper.
      For 68HC12, this scratch register is not used.  */
-  if (crtl->args.info.nregs == 2)
+  if (INCOMING_ARGS_INFO (crtl->args).nregs == 2)
     scratch = iy_reg;
   else
     scratch = ix_reg;
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	(revision 161310)
+++ gcc/config/iq2000/iq2000.c	(working copy)
@@ -1376,7 +1376,7 @@  iq2000_va_start (tree valist, rtx nextar
   /* Find out how many non-float named formals.  */
   int gpr_save_area_size;
   /* Note UNITS_PER_WORD is 4 bytes.  */
-  int_arg_words = crtl->args.info.arg_words;
+  int_arg_words = INCOMING_ARGS_INFO (crtl->args).arg_words;
 
   if (int_arg_words < 8 )
     /* Adjust for the prologue's economy measure.  */
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(revision 161310)
+++ gcc/config/ia64/ia64.c	(working copy)
@@ -3152,7 +3152,8 @@  ia64_expand_prologue (void)
   /* We don't need an alloc instruction if we've used no outputs or locals.  */
   if (current_frame_info.n_local_regs == 0
       && current_frame_info.n_output_regs == 0
-      && current_frame_info.n_input_regs <= crtl->args.info.int_regs
+      && (current_frame_info.n_input_regs
+	  <= INCOMING_ARGS_INFO (crtl->args).int_regs)
       && !TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM))
     {
       /* If there is no alloc, but there are input registers used, then we
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 161310)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -8718,10 +8718,10 @@  rs6000_va_start (tree valist, rtx nextar
 		f_sav, NULL_TREE);
 
   /* Count number of gp and fp argument registers used.  */
-  words = crtl->args.info.words;
-  n_gpr = MIN (crtl->args.info.sysv_gregno - GP_ARG_MIN_REG,
+  words = INCOMING_ARGS_INFO (crtl->args).words;
+  n_gpr = MIN (INCOMING_ARGS_INFO (crtl->args).sysv_gregno - GP_ARG_MIN_REG,
 	       GP_ARG_NUM_REG);
-  n_fpr = MIN (crtl->args.info.fregno - FP_ARG_MIN_REG,
+  n_fpr = MIN (INCOMING_ARGS_INFO (crtl->args).fregno - FP_ARG_MIN_REG,
 	       FP_ARG_NUM_REG);
 
   if (TARGET_DEBUG_ARG)
@@ -17399,7 +17399,8 @@  compute_vrsave_mask (void)
      them in again.  More importantly, the mask we compute here is
      used to generate CLOBBERs in the set_vrsave insn, and we do not
      wish the argument registers to die.  */
-  for (i = crtl->args.info.vregno - 1; i >= ALTIVEC_ARG_MIN_REG; --i)
+  for (i = INCOMING_ARGS_INFO (crtl->args).vregno - 1;
+       i >= ALTIVEC_ARG_MIN_REG; --i)
     mask &= ~ALTIVEC_REG_BIT (i);
 
   /* Similarly, remove the return value from the set.  */
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c	(revision 161310)
+++ gcc/config/arc/arc.c	(working copy)
@@ -2277,8 +2277,8 @@  static void
 arc_va_start (tree valist, rtx nextarg)
 {
   /* See arc_setup_incoming_varargs for reasons for this oddity.  */
-  if (crtl->args.info < 8
-      && (crtl->args.info & 1))
+  if (INCOMING_ARGS_INFO (crtl->args) < 8
+      && (INCOMING_ARGS_INFO (crtl->args) & 1))
     nextarg = plus_constant (nextarg, UNITS_PER_WORD);
 
   std_expand_builtin_va_start (valist, nextarg);
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(revision 161310)
+++ gcc/config/arm/arm.c	(working copy)
@@ -5059,7 +5059,7 @@  thumb_find_work_register (unsigned long 
   if (! cfun->machine->uses_anonymous_args
       && crtl->args.size >= 0
       && crtl->args.size <= (LAST_ARG_REGNUM * UNITS_PER_WORD)
-      && crtl->args.info.nregs < 4)
+      && INCOMING_ARGS_INFO (crtl->args).nregs < 4)
     return LAST_ARG_REGNUM;
 
   /* Otherwise look for a call-saved register that is going to be pushed.  */
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	(revision 161310)
+++ gcc/config/mips/mips.c	(working copy)
@@ -5472,7 +5472,7 @@  mips_va_start (tree valist, rtx nextarg)
       int fpr_save_area_size;
       int fpr_offset;
 
-      cum = &crtl->args.info;
+      cum = &INCOMING_ARGS_INFO (crtl->args);
       gpr_save_area_size
 	= (MAX_ARGS_IN_REGISTERS - cum->num_gprs) * UNITS_PER_WORD;
       fpr_save_area_size
@@ -6015,7 +6015,8 @@  mips16_build_function_stub (void)
   fprintf (asm_out_file, "\t# Stub function for %s (",
 	   current_function_name ());
   separator = "";
-  for (f = (unsigned int) crtl->args.info.fp_code; f != 0; f >>= 2)
+  for (f = (unsigned int) INCOMING_ARGS_INFO (crtl->args).fp_code;
+       f != 0; f >>= 2)
     {
       fprintf (asm_out_file, "%s%s", separator,
 	       (f & 3) == 1 ? "float" : "double");
@@ -6051,7 +6052,7 @@  mips16_build_function_stub (void)
   output_asm_insn ("la\t%^,%0", &symbol);
 
   /* Move the arguments from floating-point registers to general registers.  */
-  mips_output_args_xfer (crtl->args.info.fp_code, 'f');
+  mips_output_args_xfer (INCOMING_ARGS_INFO (crtl->args).fp_code, 'f');
 
   /* Jump to the MIPS16 function.  */
   output_asm_insn ("jr\t%^", NULL);
@@ -9814,7 +9815,7 @@  mips_output_function_prologue (FILE *fil
      floating-point arguments.  */
   if (TARGET_MIPS16
       && TARGET_HARD_FLOAT_ABI
-      && crtl->args.info.fp_code != 0)
+      && INCOMING_ARGS_INFO (crtl->args).fp_code != 0)
     mips16_build_function_stub ();
 
   /* Get the function name the same way that toplev.c does before calling
Index: gcc/config/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c	(revision 161310)
+++ gcc/config/v850/v850.c	(working copy)
@@ -1583,7 +1583,7 @@  expand_prologue (void)
     }
 
   /* Save arg registers to the stack if necessary.  */
-  else if (crtl->args.info.anonymous_args)
+  else if (INCOMING_ARGS_INFO (crtl->args).anonymous_args)
     {
       if (TARGET_PROLOG_FUNCTION && TARGET_V850E && !TARGET_DISABLE_CALLT)
 	emit_insn (gen_save_r6_r9_v850e ());
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c	(revision 161310)
+++ gcc/config/mmix/mmix.c	(working copy)
@@ -831,9 +831,9 @@  mmix_reorg (void)
      wasteful to optimize for unused parameter registers.  As of
      2002-04-30, df_regs_ever_live_p (n) seems to be set for only-reads too, but
      that might change.  */
-  if (!TARGET_ABI_GNU && regno < crtl->args.info.regs - 1)
+  if (!TARGET_ABI_GNU && regno < INCOMING_ARGS_INFO (crtl->args).regs - 1)
     {
-      regno = crtl->args.info.regs - 1;
+      regno = INCOMING_ARGS_INFO (crtl->args).regs - 1;
 
       /* We don't want to let this cause us to go over the limit and make
 	 incoming parameter registers be misnumbered and treating the last