MachineOperand SubReg

I'm working on the post-regalloc dataflow engine I mentioned yesterday.
Currently I only need to track register operands.

A MachineOperand has both a getReg() and a getSubReg() interface. For a
physical register operand, is getReg() guaranteed to be the "most super"
register with getSubReg() providing the specific subregister information
for the operand? If so then for my current purposes it seems I don't
need to worry about subregisters at all.

For reaching definitions I think simply tracking definitions via super
registers should be sufficient. Even if a definition defines a
subregister I can consider it to define the "most super" register. This
will be pessimistic for cases like x86 AH/AL, but I hardly care about
those at the moment. :slight_smile: If MachineOperand already tracks the "most
super" register then things look pretty simple as far as explicitly
defined registers go.

Anyone see any problem with this?

Thanks!

                        -David

<dag@cray.com> writes:

For reaching definitions I think simply tracking definitions via super
registers should be sufficient. Even if a definition defines a
subregister I can consider it to define the "most super" register. This
will be pessimistic for cases like x86 AH/AL, but I hardly care about
those at the moment. :slight_smile:

I did a big *facepalm* immediately after hitting "Send." If AH and AL
come in defined via separate predecessors and the block only defined AH,
then AL should remain live through the block. It would be wrong to kill
it by considering AH to define RAX.

So I do have to track sub/super register explicitly. Not difficult,
just a bit more work.

                          -David

<dag@cray.com> writes:

So I do have to track sub/super register explicitly. Not difficult,
just a bit more work.

The original question still stands, though. Is the Reg memory of
MachineOperand always the "most super" register?

                          -David

I'm working on the post-regalloc dataflow engine I mentioned yesterday.
Currently I only need to track register operands.

A MachineOperand has both a getReg() and a getSubReg() interface. For a
physical register operand, is getReg() guaranteed to be the "most super"
register with getSubReg() providing the specific subregister information
for the operand? If so then for my current purposes it seems I don't
need to worry about subregisters at all.

For physregs, getSubReg() is guaranteed to be 0. It is only used for virtual registers.

For reaching definitions I think simply tracking definitions via super
registers should be sufficient. Even if a definition defines a
subregister I can consider it to define the "most super" register. This
will be pessimistic for cases like x86 AH/AL, but I hardly care about
those at the moment. :slight_smile: If MachineOperand already tracks the "most
super" register then things look pretty simple as far as explicitly
defined registers go.

Anyone see any problem with this?

Yep, there is no such thing as a 'most super' register. The register aliasing graph is not a tree. The graph of sub/super-register relationships is also not a tree, it is a DAG.

Take a look at the ARM register bank. It demonstrates most of this stuff.

We try to track anything related to register aliasing in terms of register units. See MCRegisterInfo.h and TargetRegisterInfo.h. I believe regunits are equivalent to maximal cliques of the register aliasing graph if you're mathematically inclined.

I think it is easier to think about them as minimal sub-registers, even if that is not always completely accurate.

/jakob

Jakob Stoklund Olesen <stoklund@2pi.dk> writes:

A MachineOperand has both a getReg() and a getSubReg() interface.
For a physical register operand, is getReg() guaranteed to be the
"most super" register with getSubReg() providing the specific
subregister information for the operand? If so then for my current
purposes it seems I don't need to worry about subregisters at all.

For physregs, getSubReg() is guaranteed to be 0. It is only used for
virtual registers.

Aha! So for physregs, getSubReg() will simply be the exact physical
register defined. Cool, that'll work.

Yep, there is no such thing as a 'most super' register. The register
aliasing graph is not a tree. The graph of sub/super-register
relationships is also not a tree, it is a DAG.

Hmm. I don't doubt it but can you give me an example of a case where
there is no "most super" register? I'm having a hard time thinking up
how one would design such an ISA. Need to increase my edjimucation.

We try to track anything related to register aliasing in terms of
register units. See MCRegisterInfo.h and TargetRegisterInfo.h. I
believe regunits are equivalent to maximal cliques of the register
aliasing graph if you're mathematically inclined.

Ok, I'll check that out. MCRegisterInfo.h is new to me.

I think it is easier to think about them as minimal sub-registers,
even if that is not always completely accurate.

I'm not completely sure what you mean here.

Thanks for your help Jakob!

                          -David

Jakob Stoklund Olesen <stoklund@2pi.dk> writes:

A MachineOperand has both a getReg() and a getSubReg() interface.
For a physical register operand, is getReg() guaranteed to be the
"most super" register with getSubReg() providing the specific
subregister information for the operand? If so then for my current
purposes it seems I don't need to worry about subregisters at all.

For physregs, getSubReg() is guaranteed to be 0. It is only used for
virtual registers.

Aha! So for physregs, getSubReg() will simply be the exact physical
register defined. Cool, that'll work.

Yes, s/SubReg/Reg/

Yep, there is no such thing as a 'most super' register. The register
aliasing graph is not a tree. The graph of sub/super-register
relationships is also not a tree, it is a DAG.

Hmm. I don't doubt it but can you give me an example of a case where
there is no "most super" register? I'm having a hard time thinking up
how one would design such an ISA.

The ARM NEON D-registers are 64 bits each. NEON has vld1 instructions that can load 2, 3, or 4 consecutive D-registers.

Two consecutive D-registers is represented by the D0_D1, D1_D2, D2_D3, ... super-registers. As you can see, D1 has two super-registers, neither is more super than the other.

We similarly define triples and quads of consecutive D-registers.

NEON also has 128-bit vector instructions operating on even-odd pairs of D-registers, so the actual register names we use are: Q0, D1_D2, Q1, D3_D4, Q2, D5_D6, ... Here, Q0 is the name we use for D0_D1 (which doesn't exist).

This register structure also means that the complete set of aliasing registers can get quite large. Some NEON registers have more than 40 aliases. The register units help control that complexity. Each physreg has an associated set of regunits, and two physregs alias if and only if their regunit sets overlap. See TRI::regsOverlap().

The regunits usually correspond to the leaf sub-registers - the registers that have no sub-registers themselves. However, the numbering is different, and if you use 'Aliases = ...' in your register file, they no longer correspond exactly to the leaf registers.

/jakob

Jakob Stoklund Olesen <stoklund@2pi.dk> writes:

Aha! So for physregs, getSubReg() will simply be the exact physical
register defined. Cool, that'll work.

Yes, s/SubReg/Reg/

Right. :slight_smile:

Yep, there is no such thing as a 'most super' register. The register
aliasing graph is not a tree. The graph of sub/super-register
relationships is also not a tree, it is a DAG.

Hmm. I don't doubt it but can you give me an example of a case where
there is no "most super" register? I'm having a hard time thinking up
how one would design such an ISA.

The ARM NEON D-registers are 64 bits each. NEON has vld1 instructions that can load 2, 3, or 4 consecutive D-registers.

Two consecutive D-registers is represented by the D0_D1, D1_D2, D2_D3,
... super-registers. As you can see, D1 has two super-registers,
neither is more super than the other.

Wow, that's...interesting. :slight_smile:

This register structure also means that the complete set of aliasing
registers can get quite large. Some NEON registers have more than 40
aliases. The register units help control that complexity. Each physreg
has an associated set of regunits, and two physregs alias if and only
if their regunit sets overlap. See TRI::regsOverlap().

This must all be post-3.1 stuff since I don't see that here. Not that
I need it for x86.

Thanks for the helpful explanation!

                             -David