I’m building a backend based on LLVM 3.6 (because that was the head when I started) for a target architecture with instructions for copying between registers of different classes and also for copying literal values to registers, e.g. roughly:
TAX X A ; copy from A to X
TXA A X ; copy from X to A
TIX 42 X ; set X to 42
TIA 42 A ; set A to 42
with the instructions .TD contents roughly (omitting instruction formats, etc)
def TAX { ins aRegs:$A, outs xRegs:$X, [(set xRegs:$X, aRegs:$A)]
def TXA { ins xRegs:$X, outs aRegs:$A, [(set aRegs:$A, xRegs:$X)]
def TIX { ins imm:$val, outs xRegs:$X, [(set xRegs:$X, (imm:$val))]
def TIA { ins imm:$val, outs aRegs:$A, [(set aRegs:$A, (imm:$val))]
then when doing instruction selection for a CopyToReg(X, val) node (produced by an IR “ret i8”; calling convention has result in X0 register):
(a) with the immediate instructions TIX+TIA defined first it works, though sub-optimally:
%vreg0 = TIX 42; aRegs:%vreg0
%X0 = COPY %vreg0; aRegs:%vreg0
(b) but when TAX+TAX are defined first it selects this circular pair:
%vreg1 = COPY %vreg0; xRegs:%vreg1 aRegs:%vreg0
%vreg0 = TAX %vreg1; aRegs:%vreg0 xRegs:%vreg1
and subsequently aborts when determining liveness (“Use not jointly dominated by defs”).
Very naively I’m surprised that the order of the rule definitions matters, i.e. that it chooses the inter-register copy at all rather than finding the better-fitting literal copy. Adding cost hints such as isAsCheapAsAMove didn’t change this behaviour.
Is this the expected behaviour, or is defining TIX first just a crude workaround for some deeper problem with my code?
Thanks for whatever light you can shed…
/Tyro