Gluing arbitrary nodes together

Hello all,

I am working on adding atomics support to the AVR backend.

Because the target can only have one core, it is sufficient to:

  • Save the status register
  • Disable interrupts
  • Do the nonatomic LOAD/STORE/SWAP/ADD
  • Restore the status register

I’d really like to be able to do this at the IR level. What I want to do is write a custom lowering hook to convert ISD::ATOMIC_LOAD into a standard ISD::LOAD with the save/restore/interrupt nodes glued to it.

Here’s what I have so far:

Ping

I can’t figure out how I can glue all these nodes together and return the
nonatomic load.

How can I do this?

Your nodes should produce / consume special "glue" operand.

Hi Dylan,

As Anton said, you would need to use glue values. A node would take a glue as the last operand. That is the input glue, and will cause the node to be glued to the node that produced it. The output glue is one of the SDValues returned by the node (you can find out which one by looking at the dump).

The DAG usually like this:

Glue0 = MVT::Glue
(..., Glue1, ...) = ISD::SOME_NODE_0 Op0, Op1, ..., Glue0
(..., Glue2, ...) = ISD::SOME_NODE_1 Op0, Op1, ..., Glue1

SOME_NODE_n would be created giving it MVT::Glue as the type of the last operand. The problem is that getLoad does not accept glue operands, so there isn't an easy way to use it with loads, which, I think, is the problem you ran into.

If you want to have these nodes stick together, using glue may not be sufficient. After the machine instructions are generated, the scheduler may place instructions between the interrupt disable/restore and the atomic load itself. Also, the register allocator may insert some spills there---there are ways that this sequence may get separated.

For this, the best approach may be to define a pseudo-instruction, which will be expanded into real instruction in the post-RA expansion pass.

If you need it only for the DAG nodes, you could try to manufacture your own load via the generic getNode, forcing glue into it, but that may be more effort than it's worth. Maybe lowering it into your target-specific node would be the best approach after all?

-Krzysztof

Hey Krzysztof,

Yeah I mostly had issues with gluing the loads/stores.

After the machine instructions are generated, the scheduler may place instructions between the interrupt disable/restore and the atomic load itself. Also, the register allocator may insert some spills there—-there are ways that this sequence may get separated.

I didn’t think about that - it makes sense. It looks like building this in the MI stage is the only way.

For this, the best approach may be to define a pseudo-instruction, which will be expanded into real instruction in the post-RA expansion pass

Agree

If you need it only for the DAG nodes, you could try to manufacture your own load via the generic getNode, forcing glue into it, but that may be more effort than it’s worth. Maybe lowering it into your target-specific node would be the best approach after all?

It seems pretty tricky to construct all these manually, I agree with your point.

I will settle on pseudo instructions.

Cheers Krzysztof and Anton :slight_smile: