Hi,
I am trying to add LLVM intrinsic for a peculiar op in my ISA, which reads from r(X) but writes to r(X+1) and r(0). It seems like RegisterTuples could be used for this purpose, but I am running into a few issues lowering the intrinsic, which returns two values, to MC.
Since my target does not support spilling to stack, I will need the register allocator to allocate a register pair (say r8, r9) plus a single register (say r20), so it translates to this in MC:
my_mv r8, {src}
my_mv r20, r0 # save r0
my_op r9, r0, r8
my_mv r8, r0
my_mv r0, r20 # restore r0
Where r8 and r9 will be the return values of the intrinsic. However, as the title says, I wonder:
- I was under the assumption that return value of the last dag in
Patterndestination pattern will be the return value of the whole pattern (i.e. mapped to the return value of the intrinsic), is that correct? - How do I force a write into
r0? - How do I turn a single
RegisterTuplesof two registers into a multi-return?
For 1 and 2, my understanding was that I will have to define my own pseudo-ops, probably something like this:
def : Pattern<
(int_my_op i64:$x),
[(i64x2 (IMPLICIT_DEF:$p)),
(INSERT_SUBREG $p, $x, i64x2_odd),
(MY_MV:$tmp r0),
(INSERT_SUBREG
$p,
(MY_OP (EXTRACT_SUBREG $p, i64x2_odd)),
i64x2_even),
(INSERT_SUBREG
$p,
r0,
i64x2_odd),
(PSEUDO_WRITE_R0) $tmp),
(PSEUDO_RET_2
(EXTRACT_SUBREG $p, i64x2_even),
(EXTRACT_SUBREG $p, i64x2_odd))]>;
Where i64x2 is my RegisterTuples type, PSEUDO_WRITE_R0 writes input value to r0, and PSEUDO_RET_2 simply takes two values and returns two values (I probably need getRegAllocationHints() to make it efficient).
I wonder is there a better way to achieve this?