Patchwork Commit: RL78: Include tree-pass.h

login
register
mail settings
Submitter Nick Clifton
Date Aug. 8, 2012, 8:28 a.m.
Message ID <87a9y5aiu5.fsf@redhat.com>
Download mbox | patch
Permalink /patch/175884/
State New
Headers show

Comments

Nick Clifton - Aug. 8, 2012, 8:28 a.m.
Hi DJ,

  I am applying the following patch to the gcc mainline as an obvious
  fix for the following problem building the RL78 backend:

    gcc/config/rl78/rl78.c:151:3: error: 'PASS_POS_INSERT_BEFORE' undeclared here (not in a function)

Cheers
  Nick

gcc/ChangeLog
2012-08-08  Nick Clifton  <nickc@redhat.com>

	* config/rl78/rl78.c: Include tree-pass.h.
Richard Guenther - Aug. 8, 2012, 8:45 a.m.
On Wed, Aug 8, 2012 at 10:28 AM, Nick Clifton <nickc@redhat.com> wrote:
> Hi DJ,
>
>   I am applying the following patch to the gcc mainline as an obvious
>   fix for the following problem building the RL78 backend:
>
>     gcc/config/rl78/rl78.c:151:3: error: 'PASS_POS_INSERT_BEFORE' undeclared here (not in a function)

Err - you are inside the compiler and should not use plugin stuff to
register your machine dependent pass.

> Cheers
>   Nick
>
> gcc/ChangeLog
> 2012-08-08  Nick Clifton  <nickc@redhat.com>
>
>         * config/rl78/rl78.c: Include tree-pass.h.
>
> Index: gcc/config/rl78/rl78.c
> ===================================================================
> --- gcc/config/rl78/rl78.c      (revision 190223)
> +++ gcc/config/rl78/rl78.c      (working copy)
> @@ -48,6 +48,7 @@
>  #include "langhooks.h"
>  #include "rl78-protos.h"
>  #include "dumpfile.h"
> +#include "tree-pass.h"
>
>  static inline bool is_interrupt_func (const_tree decl);
>  static inline bool is_brk_interrupt_func (const_tree decl);
Nick Clifton - Aug. 8, 2012, 9:02 a.m.
Hi Richard,

> Err - you are inside the compiler and should not use plugin stuff to
> register your machine dependent pass.

Umm, OK, what is the correct method for registering target specific 
passes ?  (Ones that need to run at times other than 
TARGET_MACHINE_DEPENDENT_REORG).

Cheers
   Nick
Richard Guenther - Aug. 8, 2012, 9:21 a.m.
On Wed, Aug 8, 2012 at 11:02 AM, nick clifton <nickc@redhat.com> wrote:
> Hi Richard,
>
>
>> Err - you are inside the compiler and should not use plugin stuff to
>> register your machine dependent pass.
>
>
> Umm, OK, what is the correct method for registering target specific passes ?
> (Ones that need to run at times other than TARGET_MACHINE_DEPENDENT_REORG).

Have two machine_reorg passes with different target hooks.  Or schedule it twice
and have a target hook that specifies at which position it should actually run.

Richard.

> Cheers
>   Nick
>
>
Ian Taylor - Aug. 8, 2012, 1:35 p.m.
On Wed, Aug 8, 2012 at 1:45 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Aug 8, 2012 at 10:28 AM, Nick Clifton <nickc@redhat.com> wrote:
>> Hi DJ,
>>
>>   I am applying the following patch to the gcc mainline as an obvious
>>   fix for the following problem building the RL78 backend:
>>
>>     gcc/config/rl78/rl78.c:151:3: error: 'PASS_POS_INSERT_BEFORE' undeclared here (not in a function)
>
> Err - you are inside the compiler and should not use plugin stuff to
> register your machine dependent pass.

But we should definitely have a way to register machine dependent
passes, and what's wrong with the plugin interface?

Ian
Richard Guenther - Aug. 8, 2012, 2:03 p.m.
On Wed, Aug 8, 2012 at 3:35 PM, Ian Lance Taylor <iant@google.com> wrote:
> On Wed, Aug 8, 2012 at 1:45 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Wed, Aug 8, 2012 at 10:28 AM, Nick Clifton <nickc@redhat.com> wrote:
>>> Hi DJ,
>>>
>>>   I am applying the following patch to the gcc mainline as an obvious
>>>   fix for the following problem building the RL78 backend:
>>>
>>>     gcc/config/rl78/rl78.c:151:3: error: 'PASS_POS_INSERT_BEFORE' undeclared here (not in a function)
>>
>> Err - you are inside the compiler and should not use plugin stuff to
>> register your machine dependent pass.
>
> But we should definitely have a way to register machine dependent
> passes, and what's wrong with the plugin interface?

I don't think we really want that (machine dependent passes).  It seems
we cannot get away with it (so we have mdreorg).  Allowing (some) flexibility
where to put mdreorg is ok, using two different mechanisms (mdreorg and
a "plugin") sounds odd and is IMHO bad for consistency.

Richard.

> Ian
Ian Taylor - Aug. 8, 2012, 2:06 p.m.
On Wed, Aug 8, 2012 at 7:03 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:

> I don't think we really want that (machine dependent passes).  It seems
> we cannot get away with it (so we have mdreorg).  Allowing (some) flexibility
> where to put mdreorg is ok, using two different mechanisms (mdreorg and
> a "plugin") sounds odd and is IMHO bad for consistency.

I think we definitely want machine dependent passes.  E.g., reg-stack
should be one.  The passes should live by normal rules, they shouldn't
be like mdreorg.

I don't really care about the mechanism as long as it exists.

Ian
Richard Guenther - Aug. 8, 2012, 2:11 p.m.
On Wed, Aug 8, 2012 at 4:06 PM, Ian Lance Taylor <iant@google.com> wrote:
> On Wed, Aug 8, 2012 at 7:03 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>
>> I don't think we really want that (machine dependent passes).  It seems
>> we cannot get away with it (so we have mdreorg).  Allowing (some) flexibility
>> where to put mdreorg is ok, using two different mechanisms (mdreorg and
>> a "plugin") sounds odd and is IMHO bad for consistency.
>
> I think we definitely want machine dependent passes.  E.g., reg-stack
> should be one.  The passes should live by normal rules, they shouldn't
> be like mdreorg.

What is "like mdreorg"?  That it is a pass centrally registered,
called "mdreorg"
that calls a target hook which happens to implement the pass?  regstack
is controlled by a target macro and is centrally registered, too.

> I don't really care about the mechanism as long as it exists.

I was suggesting to for example register a 2nd mdreorg-like pass and
add a 2nd target hook.  regstack should get the same treatment.

Exposing machine-dependent passes in the global pass schedule makes
it easier to figure what you break - as I saw the RL78 use I wondered when
I ever grepped for the pass dump-file name in arch specific dirs when
changing that ... (never).

Richard.

> Ian
Ian Taylor - Aug. 8, 2012, 2:19 p.m.
On Wed, Aug 8, 2012 at 7:11 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Aug 8, 2012 at 4:06 PM, Ian Lance Taylor <iant@google.com> wrote:
>> On Wed, Aug 8, 2012 at 7:03 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>
>>> I don't think we really want that (machine dependent passes).  It seems
>>> we cannot get away with it (so we have mdreorg).  Allowing (some) flexibility
>>> where to put mdreorg is ok, using two different mechanisms (mdreorg and
>>> a "plugin") sounds odd and is IMHO bad for consistency.
>>
>> I think we definitely want machine dependent passes.  E.g., reg-stack
>> should be one.  The passes should live by normal rules, they shouldn't
>> be like mdreorg.
>
> What is "like mdreorg"?  That it is a pass centrally registered,
> called "mdreorg"
> that calls a target hook which happens to implement the pass?  regstack
> is controlled by a target macro and is centrally registered, too.
>
>> I don't really care about the mechanism as long as it exists.
>
> I was suggesting to for example register a 2nd mdreorg-like pass and
> add a 2nd target hook.  regstack should get the same treatment.

If the mechanism is a proliferation of mdreorg passes in every place
we want a target-specific pass, that is fine with me.

Ian
Richard Henderson - Aug. 8, 2012, 3:29 p.m.
On 08/08/2012 07:19 AM, Ian Lance Taylor wrote:
>> > I was suggesting to for example register a 2nd mdreorg-like pass and
>> > add a 2nd target hook.  regstack should get the same treatment.
> If the mechanism is a proliferation of mdreorg passes in every place
> we want a target-specific pass, that is fine with me.

I think it makes much more sense to edit the pass ordering from
the backend, rather than hooks upon hooks upon hooks.

Since the plugin interface exists, we might as well use it.


r~
DJ Delorie - Aug. 8, 2012, 3:38 p.m.
> But we should definitely have a way to register machine dependent
> passes, and what's wrong with the plugin interface?

IIRC I asked about how to schedule that pass when I wrote it, and "use
the plugin API" was the recommendation.

Some background...

The RL78 devirtualization pass is *not* a reorg pass, it has to happen
after reload but before debug info is set up.  The RL78 does not have
a consistent register set or addressing scheme, GCC cannot practically
support it.  So RL78 uses a virtual register set and machine
description until after reload, then copy data in and out of the
virtual registers to physical registers depending on the operations
required.  The only way to get decent performance and reasonable
debugging is to do that pass as soon after reload as possible, so the
remaining optimizations can work with real registers.

Basically, after the RL78 devirtualization pass, the RL78 is a
completely different target machine.
Mike Stump - Aug. 8, 2012, 5:52 p.m.
On Aug 8, 2012, at 8:38 AM, DJ Delorie wrote:
> The RL78 devirtualization pass is *not* a reorg pass, it has to happen
> after reload but before debug info is set up.  The RL78 does not have
> a consistent register set or addressing scheme, GCC cannot practically
> support it.

Gosh, we got one of those two, though, I don't know how much worse your machine is than mine, in at all.  For example, $fp is in register N, where N is calculated differently for each function and isn't known until compute_frame_size time.  Which registers can be used isn't known until then either.  Also, different parts of the prologue use totally different numbering.  We handle this by having many different copies of all the registers, one copy for each possible category of use, and the once we get a feel for the landscape, we pin everything (that's a lie, we only pin some things) down, mark up which registers are going to be disappeared or put into service, essentially, for a given register, it can only ever be live in one category.  Some of the categories have variable mappings (computed mappings) to the actual register, it isn't the case that the first register of category Y, maps to the same register as the first register of category Z. We also have different mappings depending where in the instruction stream the instruction falls, just for fun.  Now, we do all this, with no reorg or devirtualization pass.  I'd like to think what you do would be a proper subset of what we do.

So, for example, we have one category for call clobbered registers, one for caller saved register, one for inbound argument register, one for outbound argument registers, gosh, so many, I can't recall all the others...  The only magic we do have, is an extra call to reinit_regs in gimple_expand_cfg right before the if () fixup_tail_calls() code, so that TARGET_CONDITIONAL_REGISTER_USAGE has a chance to fire at just the right time.  That firing pins some of the aspects of argument registers and some of the other registers.  The rest of the pinning down is done at compute_frame_size time.  So, there isn't just one pinning, but two.  We handle the second pinning by dynamic code in print_operand.  regno = func (regno, codegen_state); printf ("%s", reg_name[regno]);  The style allows for an arbitrarily computed register number, based upon anything one wants.  We merely happen to use the frame information, leaf information, where in the instruction stream we are and a few other bits.  Our usual func, is something like:

  switch CATEGORY (regno)
    case 1:
	regno = regno-CATEGORY_BASE[1] + actual_start_category[1];  break;
    case 2:
        regno = regno-category_base[2] + actual_start_category[2];  break;
   [ ... ]

where the various category_bases are the start of the given categories and the actual_start_categories are the place to actually put the category in the actual register file.

So, if you want to explore how to redo the port, or if it is even possible, just let me know...  I like puzzles, but only if they aren't trivial.  :-)  The line count to switch your port is roughly O(NC*(ARPC/4 + 20) + 80), I suspect; where NC are the number of classes, and ARPC is the average registers per class.

Now, all that said, the code is pretty basic and clean and we think interfaces well with the rest of the compiler.  We don't violate gcc notion of codegen (though, we might get the DBX_REGISTER_NUMBER slightly wrong in the first part of the prologue).  I think even that problem can be fixed, if we want.

As we move to C++, I'd love for port maintainers to be able to get together and hoist _up_ code from the port so other ports can use it and thus, have more sharing.  We make heavily stylized uses, which could be wrapped into a prettier api, given a reasonably powerful language.  C++ might be powerful enough.  I'd love to see someone improve the FIXED_REGISTERS, REGISTER_NAMES, REG_CLASS_CONTENTS, REGNO_REG_CLASS, REGNO_GLOBAL_BASE_REG_P, CLASS_MAX_NREGS experience, as the current api sucks; for example.  I dread the slightest change to any of my registers, as the change ripples throughout a ton of disparate places, and it is currently too easy to forget one of them.  Bonus points for cleaning up TARGET_SECONDARY_RELOAD at the same time as the above.  I find that api sucks in ways I can't begin to describe.
DJ Delorie - Aug. 8, 2012, 6:14 p.m.
> Gosh, we got one of those too, though, I don't know how much worse
> your machine is than mine, in at all.

In the RL78 case, it's basically a modern Z80 clone.  It has eight
8-bit registers (er, four banks of those, one active at a time) which
can be combined into four 16-bit registers, but for each addressing
mode there's specific register pairs that can be used as base
registers, and sometimes the "base register" is 8-bits and sometimes
it's 16, and sometimes you can combine them (i.e. [HL+B]) in weird
ways.  Worse, most of the MOV operations and all of the math/logic
operations *only* use the A/AX register, and the ones that use other
registers are often asymmetrical.  For example, you can move data from
memory to BC, but not from BC to memory.

It's the weird addressing modes that confuse gcc.  (I had similar
problems with the m32c port, although it was "clean" enough to
eventually force it to work right.  Er, "right enough".  There's still
one double-indirect addressing mode that I can't tell gcc about
because it makes reload vomit.)

Fortunately, there's an addressing mode that covers a small range of
RAM with relatively flexible addressing, and that range happens to
overlap the memory-mapped registers.  So, we tell GCC to use some of
that memory as "virtual registers" and after reload the
devirtualization pass shuffles data in and out of real registers to do
whatever operations are required, based on what addressing modes are
used and what operations need be done.  The post-reload optimizations
then clean up unneeded moves etc.

I.e. we built a micro-interpreter with a compile-time JIT :-)

To do this, we have separate "virtual" and "real" *.md files and
patterns, and the devirtualizer has some standard rules for copying
data, which it applies until the pattern's predicates and constraints
match.  There are some hints in the patterns to tell it which rules to
use, too.  We do a recog on the virtual pattern to get the hints and
operands, then recog on the real one until it works.

> As we move to C++, I'd love for port maintainers to be able to get
> together and hoist _up_ code from the port so other ports can use it
> and thus, have more sharing.

The one bit of code I seem to need more often than usual is an
"unneeded move elimination" pass or helper.  I'd like to be able to
call that at arbitrary times after (or before, or during) other passes
to clean up unneeded moves.  My implementations are fairly trivial
because they cater to my ports, but a generic one that covers all
ports generically would be much more appropriate.
Nathan Froyd - Aug. 8, 2012, 6:16 p.m.
On Wed, Aug 08, 2012 at 10:52:28AM -0700, Mike Stump wrote:
> As we move to C++, I'd love for port maintainers to be able to get together and hoist _up_ code from the port so other ports can use it and thus, have more sharing.  We make heavily stylized uses, which could be wrapped into a prettier api, given a reasonably powerful language.  C++ might be powerful enough.  I'd love to see someone improve the FIXED_REGISTERS, REGISTER_NAMES, REG_CLASS_CONTENTS, REGNO_REG_CLASS, REGNO_GLOBAL_BASE_REG_P, CLASS_MAX_NREGS experience, as the current api sucks; for example.  I dread the slightest change to any of my registers, as the change ripples throughout a ton of disparate places, and it is currently too easy to forget one of them.  Bonus points for cleaning up TARGET_SECONDARY_RELOAD at the same time as the above.  I find that api sucks in ways I can't begin to describe.

Would a registers.md for defining registers and register classes
(and maybe things like FIXED_REGISTERS and the like) be a good
start for you, or do you want something more developed first?

-Nathan
Mike Stump - Aug. 8, 2012, 10 p.m.
On Aug 8, 2012, at 11:16 AM, Nathan Froyd wrote:
> On Wed, Aug 08, 2012 at 10:52:28AM -0700, Mike Stump wrote:
>> As we move to C++, I'd love for port maintainers to be able to get together and hoist _up_ code from the port so other ports can use it and thus, have more sharing.  We make heavily stylized uses, which could be wrapped into a prettier api, given a reasonably powerful language.  C++ might be powerful enough.  I'd love to see someone improve the FIXED_REGISTERS, REGISTER_NAMES, REG_CLASS_CONTENTS, REGNO_REG_CLASS, REGNO_GLOBAL_BASE_REG_P, CLASS_MAX_NREGS experience, as the current api sucks; for example.  I dread the slightest change to any of my registers, as the change ripples throughout a ton of disparate places, and it is currently too easy to forget one of them.  Bonus points for cleaning up TARGET_SECONDARY_RELOAD at the same time as the above.  I find that api sucks in ways I can't begin to describe.
> 
> Would a registers.md for defining registers and register classes
> (and maybe things like FIXED_REGISTERS and the like) be a good
> start for you, or do you want something more developed first?

I think I'd rather have a nice general purpose C++ library that has a nice api that can generate code.  Longer term, it'd be nice to refactor all the gen*.c code to use the library.  The problem with the current gen*.c scheme is there is no flexibility to do anything that wasn't preconceived.  So, for example, mode iterators had to be added, a user of the library, can't just slot in 20 lines and have them.  I had mode iterators in a port I did, a long time before we had them in gcc, but, since there wasn't a way to slot them in, that meant no one had them for years and years.  Sad.  I can't just slot in 100 lines to 'solve' the register issue.  I'd like, not a solution to the register problem, but, rather a library, that is compete enough, to let me solve the register problem.

The register case, maybe is too trivial to show what I mean, for example, here is 113 lines that solves a part of the problem.  Not a big deal, but, we don't have an easy enough way to do this and a culture that encourages innovative solutions.  20 years later, and the same old gross api still is the only way to do it.  Consider the below code.  Notice that I can do, pretty much anything I need with it.  At first, it didn't generate FIXED_REGISTERS, then, a few trivial lines later, it did.  The it didn't handle aliases, then a few lines later, then it did.  The bits are trivial and obvious for anyone to add.  The api is nice and flexible and can sport many different ways to doing things, and, even if all of them are compete failures, one can _always_ layer _anything_ they want on top of the trivial interface and do anything they want to solve the problem they face.  Notice the addition of regs, you can now do an entire register file with 1 line.  My feeling is that we should have a recommend best practice.  Those ports that don't, or didn't follow the best practice, are larger; those that do, are smaller.  In this case, the best practice, if regs is it, is 1 line.  You can add aliases, easy to use register names for parameters, with those being preferred, the usual names for the rest of them and so on.

Also, if all the ports switched to it, then one can actually change FIXED_REGISTERS to be completely different, merely by changing the implementation of the api, once.  One can move a register around, thus renumbering all the register, and reordering all the bits in the bits array, without any carefulness or fear.  One can add a new register, without fear of missing anything, anywhere (within the scope of the generated code).  If one wanted to add support for MODE_OK, or NREGS, or CANNOT_CONVERT, again, trivial to do, and possible to do in an incremental fashion.  Notice how I added aliases, while still retaining compatibility with existing users of the api.  Want to add FRAME_POINTER_REGNUM support, easy to do, just invent an nice api you like, and bolt it in.  Want to revamp an api, easy put them in a namespace and put in a using regs_v1, newer code can do a using reg_v2.  Eventually regs_v1 can be deleted, or not, or even moved into the last port file that uses it.

Now, imagine a nice pretty api for secondary_reload.  :-)  Or vectors, or move instructions, or legitimate or legitimize... or  imagine what:

gen_const_int_pred(1, 4, 8, 14, 22, 32, 48, 64);

could do.  (Hint, generate predicates with stylized names for all of the given N-bit constants.)  Much nicer, less typing, easier to maintain...  We know exactly how to write the above, but only in a real language, C++ should be sufficient.  genpred.c will _never_ and can never do this, no matter that it is what, five lines of code, given the stuff on which to build this on top of.  This is _why_ the gen*.c things are the wrong architecture.


#include <stdio.h>
#include <strings.h>

enum { BITS_PER = 64 };
enum style {
  Fixed,
  Saved,
  Vol };

class r {
  enum { N = 1024 };
  static int count;
  static const char *names[N];
  static int fixed[N];
  static const char *alias[N];
 public:
  r(const char *name, enum style s, const char *a = 0) {
    names[count] = name;
    if (s == Fixed)
      fixed[count] = 1;
    alias[count] = a;
    ++count;
  }
  r(const r &o) { }
  static int get_count() { return count; }
  static const char *get_name(int i) { return names[i]; }
  static const char *get_alias(int i) { return alias[i]; }
  static int get_fixed(int i) { return fixed[i]; }
};

const char *rn(int i, const char *prefix = "%r") {
  char buf[30];
  sprintf (buf, "%s%d", prefix, i);
  return strdup (buf);
}

int r::count = 0;
const char *r::names[sizeof (r::names)/sizeof(r::names[0])];
const char *r::alias[sizeof (r::alias)/sizeof(r::alias[0])];
int r::fixed[sizeof (r::fixed)/sizeof(r::fixed[0])];

class fr : public r {
public:
  fr(const char *name) : r(name, Fixed) { }
  fr(const fr &o) : r(o) { }
};

class vr : public r {
public:
  vr(const char *name, const char *a = 0) : r(name, Vol, a) { }
  vr(const fr &o) : r(o) { }
};

int main() {
  printf("#define REGISTER_NAMES \\\n");
  printf("  {");
  for (int i = 0; i < r::get_count(); ++i)
    {
      printf(" \"%s\"", r::get_name(i));
      if (i < r::get_count()-1)
	printf(",");
    }
  printf(" }\n");
  printf("\n");

  printf("#define FIXED_REGISTERS \\\n");
  printf("  {");
  long l = 0;
  int i;
  for (i = 0; i < r::get_count(); ++i)
    {
      l <<= 1;
      l |= r::get_fixed (i);
      
      if (i%BITS_PER == (BITS_PER-1))
	{
	  printf(" 0x%lx", l);
	  l = 0;
	  if (i < r::get_count()-1)
	    printf(",");
	}
    }
  if (i%BITS_PER != (BITS_PER-1))
    printf(" 0x%lx", l);
  printf(" }\n");
  printf("\n");

  printf("#define ADDITIONAL_REGISTER_NAMES \\\n");
  printf("  {");
  bool need = false;
  for (int i = 0; i < r::get_count(); ++i)
    {
      if (r::get_alias(i))
	{
	  if (need)
	    printf(",");
	  printf(" {\"%s\", %d}", r::get_alias(i), i);
	  need = 1;
	}
    }
  printf(" }\n");
  printf("\n");
}

class regs {
public:
  regs(int parms, int vol, int total) {
    for (int i=0; i<parms; ++i)
      vr(rn(i, "%a"), rn(i));
    for (int i=parms; i<vol; ++i)
      vr(rn(i));
    for (int i=vol; i<total; ++i)
      r(rn(i), Saved);
  }
};





regs gprs(4, 8, 32);

fr fregs[] = { "fr1", "fr2", "fr3", "fr4" };
vr vregs[] = { "vr1", "vr2", "vr3", "vr4" };
r r1("r1", Fixed);
r r2("r2", Fixed);
r r3("r3", Vol);
r r4("r4", Saved);
r r5("r5", Fixed);
r r6("r6", Fixed);
r r7("r7", Fixed);
r r8("r8", Fixed);
r r9("r9", Fixed);
r r10("r10", Fixed);
r r11("r11", Fixed);
r r12("r12", Fixed);
r r13("r13", Fixed);
fr fr1("fr1");
fr fr2("fr2");
fr fr3("fr3");


class gen {
public:
  gen() {
    for (int i = 0; i < 64; ++i)
      {
	fr (rn(i));
      }
  }
} a;





when run, this produces:

$ g++ reg.c && ./a.out
#define REGISTER_NAMES \
  { "%a0", "%a1", "%a2", "%a3", "%r4", "%r5", "%r6", "%r7", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31", "fr1", "fr2", "fr3", "fr4", "vr1", "vr2", "vr3", "vr4", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "fr1", "fr2", "fr3", "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31", "%r32", "%r33", "%r34", "%r35", "%r36", "%r37", "%r38", "%r39", "%r40", "%r41", "%r42", "%r43", "%r44", "%r45", "%r46", "%r47", "%r48", "%r49", "%r50", "%r51", "%r52", "%r53", "%r54", "%r55", "%r56", "%r57", "%r58", "%r59", "%r60", "%r61", "%r62", "%r63" }

#define FIXED_REGISTERS \
  { 0xf0cfffff, 0xffffffffffffff }

#define ADDITIONAL_REGISTER_NAMES \
  { {"%r0", 0}, {"%r1", 1}, {"%r2", 2}, {"%r3", 3} }
Mike Stump - Aug. 8, 2012, 10:29 p.m.
On Aug 8, 2012, at 11:14 AM, DJ Delorie wrote:
> It's the weird addressing modes that confuse gcc.

Ah, yes...  That problem.  Sigh, my port is nice and orthogonal and doesn't suffer in this area, so... no solution from me.
Richard Guenther - Aug. 9, 2012, 8:12 a.m.
On Wed, Aug 8, 2012 at 5:29 PM, Richard Henderson <rth@redhat.com> wrote:
> On 08/08/2012 07:19 AM, Ian Lance Taylor wrote:
>>> > I was suggesting to for example register a 2nd mdreorg-like pass and
>>> > add a 2nd target hook.  regstack should get the same treatment.
>> If the mechanism is a proliferation of mdreorg passes in every place
>> we want a target-specific pass, that is fine with me.
>
> I think it makes much more sense to edit the pass ordering from
> the backend, rather than hooks upon hooks upon hooks.
>
> Since the plugin interface exists, we might as well use it.

The issue is that using the plugin interface makes breakage only detectable
when you are able to test a target, not by merely building it.  That's bad
(of course only for those weirdo targets).  We should _at least_ provide
an interface to internals that for example use the address of the pass
structure for pass placement instead of just the dump file name.

Richard.

>
> r~
DJ Delorie - Aug. 9, 2012, 4:45 p.m.
> The issue is that using the plugin interface makes breakage only
> detectable when you are able to test a target, not by merely
> building it.

You just described *most* of the bugs I have to deal with.

Patch

Index: gcc/config/rl78/rl78.c
===================================================================
--- gcc/config/rl78/rl78.c	(revision 190223)
+++ gcc/config/rl78/rl78.c	(working copy)
@@ -48,6 +48,7 @@ 
 #include "langhooks.h"
 #include "rl78-protos.h"
 #include "dumpfile.h"
+#include "tree-pass.h"
 
 static inline bool is_interrupt_func (const_tree decl);
 static inline bool is_brk_interrupt_func (const_tree decl);