This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Beyond Complex Register Management


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]