More address registers

Hi again,
I’m finally getting some time to work on my m68k backend again. :slight_smile:

I was trying to solve the problem that loads from arbitrary addresses need to go through address registers. 68k allows flexible addressing similar to what the x86 can do, only that the adressing base has to reside in an address register:

move.size[b/w/l] (Ax, Dx * Scale[1/2/4/8]), – Dest = *(Ax + Displacement + Dx * Scale)

This is very powerful and suits a variant of the X86 backend SelectAddr() pretty well, so I’ve adapter pieces of that code for my own little backend.

The issue I’m pondering is how to ensure that addresses end up in address registers just before the load. We discussed different alternatives on the list a while back such as pseudo registers and fixup passes; but then today I sat down again and tried something really stupid. In my SelectAddr() hook, which I know is going to be attempted for all loads, I can simply augment the source of the load to include a register copy so I know it’s guaranteed to be loading from the correct register class in the end.

I tried mocking this up using the following. (Base is what’s returned as the Ax in the move expression above when the DAG is constructed due to SelectAddr().)

SDOperand chain = CurDAG->getCopyToReg(Base, M68K::A3, Base);
Base = CurDAG->getCopyFromReg(chain, M68K::A3, MVT::i32);

This actually generates valid, but horrible code:

int deref(int *p) { return *p; } gives

move.l a0, a3 – a0 is a live in (first pointer arg)
move.l (a3), d0 – d0 is a live out (first integer return value)
rts

int deref(int **p) { return **p; } gives

move.l a0, a3
move.l (a3), d0
move.l d0, a3
move.l (a3), d0
rts

Could this work (given there’s a way to correctly get a hold of a virtual register of address type rather than hard coding A3) or am I missing something?

// Andreas

2008/2/15, Andreas Fredriksson <deplinenoise@gmail.com>:

I tried mocking this up using the following. (Base is what’s returned as the Ax in the move expression above when the DAG is constructed due to SelectAddr().)

SDOperand chain = CurDAG->getCopyToReg(Base, M68K::A3, Base);
Base = CurDAG->getCopyFromReg(chain, M68K::A3, MVT::i32);

Replying to myself here.

This worked a bit better :slight_smile:

const unsigned addressReg = RegMap->createVirtualRegister(&M68K::AR32RegClass);
SDOperand chain = CurDAG->getCopyToReg(Base, addressReg, Base);
Base = CurDAG->getCopyFromReg(chain, addressReg, MVT::i32);

// Andreas

2008/2/15, Andreas Fredriksson <deplinenoise@gmail.com>:

I tried mocking this up using the following. (Base is what’s returned as the Ax in the move expression above when the DAG is constructed due to SelectAddr().)

SDOperand chain = CurDAG->getCopyToReg(Base, M68K::A3, Base);
Base = CurDAG->getCopyFromReg(chain, M68K::A3, MVT::i32);

Replying to myself here.

This worked a bit better :slight_smile:

const unsigned addressReg = RegMap->createVirtualRegister(&M68K::AR32RegClass);
SDOperand chain = CurDAG->getCopyToReg(Base, addressReg, Base);
Base = CurDAG->getCopyFromReg(chain, addressReg, MVT::i32);

This probably will produce correct code since the copy source and destination registers are of different register classes it’s not in danger of being coalesced away. But as you have seen, it’ll produce poor code. I think it’s a reasonable step in the right direction though.

Evan