This is the mail archive of the gcc@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]

How to hide registers from local RA but not reload?



   Hello Gcc hackers,

  I don't even know if what I'm doing is supposed to be possible, but I'm
trying it anyway!

  To oversimplify the situation, I've got an external memory-mapped peripheral
that does multiply operations.  It's got three SImode registers; you write a
word each to the multiplier and multiplicand, and a few cycles later you read
back the result from the result register.

  So my first idea to make this work is to treat each of the peripheral's
memory locations as if they were actually hard regs.  My strategy is 

 - allocate hard reg numbers to each of these registers

 - define a reg class for each of these registers, with a single member in
each, corresponding to the given (fake) hard register.

 - define md constraint letters for each of these classes.

 - implement the mulsi3 pattern, accepting only register operands and using
the constraint letter on each operand that corresponds to the relevant
hard(ware) register.

 - implement movsi3 alternatives to move between a general register and each
of the single-member reg classes (these are actually memory load/stores in
disguise as reg-reg moves).

 - allow reload to take care of moving the operands for mulsi3 insns into the
relevant pseudo-hardregs by using the movsi3 patterns.


  However, the last thing I want is for the register allocater to decide it's
a good idea to ever allocate one of these registers for general usage, because
they're really memory locations; using one to store a pseudo would be
basically the same as spilling it to the stack.

  Trying to mark them as FIXED_REGs didn't work, as it meant reload didn't
even think it could use them, so I settled for leaving them unFIXED, but not
mentioning them in the REG_ALLOC_ORDER.

  This initially appeared to have the desired effect; at any rate, it
generated correct assembly code for mulsi3 operations.  But it has had some
undesirable knock-on effects; it perturbs the lreg pass in a bad way.

  The intermediate cause is that lreg considers all the special-purpose reg
classes when allocating, and for some reason decides that several of the
special-purpose classes have equal cost (zero) to GENERAL_REGS.  The bit I
find strange about this is that it then decides to take the highest-numbered
class as the preferred register class, despite the fact that it has a lot less
members in it than GENERAL_REGS.  (There is no overlap between the classes, so
I haven't put them in the "wrong order", as one is not a subset of the other).

  Anyway, somehow this preference throws things off, and it *looks* like it
ends up assuming it needs yet another register to reload into the specialised
class reg, and then it eliminates the original register and the overall effect
is that instead of allocating a consecutive bunch of hard regs starting with
my volatile arg-passing regs, it leaves gaps in the range and allocates
further registers beyond the end of it, so a routine that previously got
allocated r1 to r6 (r1-r4 are function arg-passing regs in this setup) might
end up using r1 to r5 and r7.


  Which leads to one or two questions:

Q.  Is it possible to do what I really want: to make the compiler aware of
some registers, but limit their usage to a single insn; to allow reload to use
these registers when directed to by a constraint letter, but for the rest of
the compiler to basically pretend they don't even exist.

Q.  Would it perhaps work better if I didn't rely on reload to move args into
the specialised registers, but used an expander or splitter to generate the
sequence of store operand 1 to multiplier register, store operand 2 to
multiplicand register, load operand zero from result register?  I wouldn't
need to mess around with register classes at all, but I might have problems
controlling the scheduling and sequencing of the operations - you have to load
the two input registers in the correct order, since loading the second one
triggers the operation.

Q.  Or should I just adjust the costs of these registers to something
ludicrous, so that they would never ever seem to be preferable to any other
register nor even a memory spill, and not worry about whether it thinks they
are allocatable or not?



    cheers,
      DaveK
-- 
Can't think of a witty .sigline today....


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