Custom load/store code: determining offset or alignment

Firstoff, let me say what a mind fsck the Cell SPU can be. It's really
not that hard an architecture to get one's mind around, but I can see
how it becomes a compiler writer's nightmare.

And I'm attempting to write a SPU backend. And it's going slowly.

Here's my problem: The SPU's registers are all 128-bit vector registers.
That's their native mode. They can be used as 8-, 16-, and 32-bit
registers for PODs, with certain result propagation consequences. For
example, you can load a constant into a register's "preferred slot"
(where POD data goes), but the constant propagates to all other vector
elements (making scalar_to_vector transforms significantly easier, but
that's beside the point here.) Moreover, to get what is termed
"unaligned" POD data from its vector element into the preferred slot
requires doing vector perm-ing and shuffling.

Consequently, this unique register set makes writing the instruction
description significantly more challenging. Loads and stores for PODs
and non-vector types (seemingly) have to be custom lowered in
TargetLowering::LowerOperation and custom selected in
SelectionDAGISel::Select.

Q1: Is there any way I can determine a POD's offset and check its
    alignment as a predicate in the tblgen files? If so, this would
    likely take care of the normal case if the POD is on the stack
    and writing patterns is a lot easier than custom selecting or
    lowering.

Q2: Is there any way to determine a POD's offset based on a LoadSDNode
    and StoreSDNode's data? Currently, LoadSDNode::getBasePtr (and
    StoreSDNode::getBasePtr) can return something back, but how do I
    access the operand's offset (and hence, alignment) relative to a
    base register?

Q3: There are three variants of load (and store) for the SPU. Two of the
    variants take 10- and 16-bit sign extended offsets, whereas the
    third is reg+reg. If I have to custom lower and select, knowing the
    offset would make it easier to determine which variant to use, if
    tblgen pattern matching isn't an option. Can I do this?

Do my questions make sense?

-scooter

PS: Off for the weekend. It's not vacation. But I'm hoping there'll be
some interesting suggestions to read on Monday morning.

Firstoff, let me say what a mind fsck the Cell SPU can be. It's really
not that hard an architecture to get one's mind around, but I can see
how it becomes a compiler writer's nightmare.

:slight_smile:

And I'm attempting to write a SPU backend. And it's going slowly.

ok

Here's my problem: The SPU's registers are all 128-bit vector registers.
That's their native mode. They can be used as 8-, 16-, and 32-bit
registers for PODs, with certain result propagation consequences. For
example, you can load a constant into a register's "preferred slot"
(where POD data goes), but the constant propagates to all other vector
elements (making scalar_to_vector transforms significantly easier, but
that's beside the point here.) Moreover, to get what is termed
"unaligned" POD data from its vector element into the preferred slot
requires doing vector perm-ing and shuffling.

Ok.

Consequently, this unique register set makes writing the instruction
description significantly more challenging. Loads and stores for PODs
and non-vector types (seemingly) have to be custom lowered in
TargetLowering::LowerOperation and custom selected in
SelectionDAGISel::Select.

Q1: Is there any way I can determine a POD's offset and check its
   alignment as a predicate in the tblgen files? If so, this would
   likely take care of the normal case if the POD is on the stack
   and writing patterns is a lot easier than custom selecting or
   lowering.

Yes. The Load/StoreSDNode both keep an alignment of the access. You should base your code off this. I don't think that this field is currently used by much, so you may find bugs in its computation. Further, we should add some analysis to the dag combine pass which uses analysis to increase the alignment field of the load/store when it can prove that it is safe.

Q2: Is there any way to determine a POD's offset based on a LoadSDNode
   and StoreSDNode's data? Currently, LoadSDNode::getBasePtr (and
   StoreSDNode::getBasePtr) can return something back, but how do I
   access the operand's offset (and hence, alignment) relative to a
   base register?

Offset from what?

Q3: There are three variants of load (and store) for the SPU. Two of the
   variants take 10- and 16-bit sign extended offsets, whereas the
   third is reg+reg. If I have to custom lower and select, knowing the
   offset would make it easier to determine which variant to use, if
   tblgen pattern matching isn't an option. Can I do this?

Typical backends defer address mode selection until the 'select' pass. You want to know the offset at lowering time?

-Chris