Hi All,
My target has 32bit registers, but it has some 64bit instructions which are using pairs of these 32bit registers.
I have defined registers, aliases and subregister set.
The problem is that register allocator is using 32bit registers that are already used in a pair, for example:
lw $r0, 16[$r12] // load word to r0
ld $p0, 36[$r12] // load doubleword to p0
shl $p0, $p0, $r0 // shift left p0 by r0 and store result in p0
where p0 is a pair r0:r1
Could anyone tell me what am I doing wrong?
Thanks in advance
Artur
Hello, Artur
I have defined registers, aliases and subregister set.
The problem is that register allocator is using 32bit registers that are
already used in a pair, for example:
lw $r0, 16[$r12] // load word to r0
ld $p0, 36[$r12] // load doubleword to p0
shl $p0, $p0, $r0 // shift left p0 by r0 and store result in p0
where p0 is a pair r0:r1
Could anyone tell me what am I doing wrong?
Have you defined aliases properly? Look how this is handled inside
s390 backend (systemz).
Note that in general you'll need to write "paired" reg-reg mov pseudo
instructions.
Hi Anton,
Thanks for reply
I have defined registers, aliases and subregister set.
The problem is that register allocator is using 32bit registers that are
already used in a pair, for example:
lw $r0, 16[$r12] // load word to r0
ld $p0, 36[$r12] // load doubleword to p0
shl $p0, $p0, $r0 // shift left p0 by r0 and store result in p0
where p0 is a pair r0:r1
Could anyone tell me what am I doing wrong?
Have you defined aliases properly? Look how this is handled inside
s390 backend (systemz).
I’ve compared again everything to systemz. The problem was I’ve defined paired class as a subclass of Register class instead of RegisterWithSubRegs class. After change the code is OK.
Note that in general you’ll need to write “paired” reg-reg mov pseudo
instructions.
Yes, I have those.
If you don’t mind I’ll ask few compilers/LLVM newbie questions.
I’d appreciate if someone could enlighten me on pseudo instructions.
These work fine if I want to print assembly. What if I want to generate a binary file directly: how can I expand something like this:
mov $p0, $p1
into two instructions:
mov $r0, $r2
mov $r1, $r3
Another problem: All of my instructions which operates on 64bit operands, take pairs of 32bit registers. However in some of these instructions registers are encoded as a pair number and in some as two single register numbers for each pair.
Similar problem with immediates which not fit in 10bits - they are encoded as separate upper22 bits and lower10 bits (64 bits long version of instruction instead of 32 bits).
Thanks a lot for explanation/suggestions
Artur
A related question: GCC does the same for 64-bit args in two 32-bit
registers, but always uses (Rn, Rn+1) pairs and is incapable of
scheduling the two 32-bit move instructions independently, since the
two are output at the very last minute by the last part of the
machine-dependent backend/
This is slow when moving such a 2x32-bit value to a 64-bit register in
one the ARM FPUs, since two 32-bit moves to the low and high halves
of the same FPU register incur a 7-cycle delay - a fairly common
occurrence when double args are moved into FPU regs for processing. If
it could schedule the two 32-bit moves separately, up to 6 other
instructions could be executed in the mean time.
The only answer in GCC seems to be a further optimization pass in the
back end performed after the assembly generation pass has been done,
to shuffle the adjacent inns when they don't supply or depend on the
moved values - horrid.
I was wondering if this would be more practical in LLVM (of which I am
ignorant but curious) or whether the illusion of a single 64-bit
register also persists there until it is too late.
Cheers
M
Artur Pietrek wrote:
I'd appreciate if someone could enlighten me on pseudo instructions.
These work fine if I want to print assembly. What if I want to generate
a binary file directly: how can I expand something like this:
mov $p0, $p1
into two instructions:
mov $r0, $r2
mov $r1, $r3
Another problem: All of my instructions which operates on 64bit
operands, take pairs of 32bit registers. However in some of these
instructions registers are encoded as a pair number and in some as two
single register numbers for each pair.
Similar problem with immediates which not fit in 10bits - they are
encoded as separate upper22 bits and lower10 bits (64 bits long version
of instruction instead of 32 bits).
I can't help you directly, but I can point you in the right direction.
Take a look at the 'MC' library. This is the library that's responsible
for generating native binary code. (It's not finished yet, by the way.)
If you want this kind of support from LLVM, you'll have to hook your
backend into MC.
Chip
Hello, Artur
I've compared again everything to systemz. The problem was I've defined
paired class as a subclass of Register class instead of RegisterWithSubRegs
class. After change the code is OK.
Ok, nice
Yes, I have those.
If you don't mind I'll ask few compilers/LLVM newbie questions.
I'd appreciate if someone could enlighten me on pseudo instructions.
These work fine if I want to print assembly. What if I want to generate a
binary file directly: how can I expand something like this:
mov $p0, $p1
into two instructions:
mov $r0, $r2
mov $r1, $r3
Well, just have a post-RA pass, which expands these
pseudo-instructions into real ones? Look how things are performed on
ARM.
This is general goodness for post-RA scheduler as well.
Another problem: All of my instructions which operates on 64bit operands,
take pairs of 32bit registers. However in some of these instructions
registers are encoded as a pair number and in some as two single register
numbers for each pair.
Similar problem with immediates which not fit in 10bits - they are encoded
as separate upper22 bits and lower10 bits (64 bits long version of
instruction instead of 32 bits).
So, what's the problem here? All such weirdness should be handled
inside code emitter....
Hello, Martin
I was wondering if this would be more practical in LLVM (of which I am
ignorant but curious) or whether the illusion of a single 64-bit
register also persists there until it is too late.
It makes sense to have such pseudo-instructions up to RA - this
simplifies many things alot. However, one can do a post-RA Machine
Instruction pass and split such pseudo-instructions into "normal"
ones. post-RA scheduler will be happy to schedule the single
instructions to ensure necessary latencies.
This is already done for movt/movw pairs on ARM.
Hi Anton,
I’ve compared again everything to systemz. The problem was I’ve defined
paired class as a subclass of Register class instead of RegisterWithSubRegs
class. After change the code is OK.
Ok, nice
Just one more question. Shouldn’t register class Rd in Sparc backend be a subclass of RegisterWithSubRegs class?
Thanks again for explanation.
Artur