How to represent two-address instruction with TableGen?

I’m new to LLVM backend and is developing for a custom ISA which instruction has two addresses.
For example:
add $r0,$1 means r0=r0+r1.

Previously I just declare two operands for add as following:

"add $dst,$src"
(outs GPR64:$dst)
(ins GPR64:$src)

However when I tried to add ISel patterns to this instruction with the following pattern:

(set GPR64:$dst,(add GPR64:$src,GPR64:$dst))

I received error:

In ADDRR: Input operand $dst occurs in pattern but not in operands list!

Not sure about what I did wrong here, any hint would be much appreciate

You’ll need to declare two sources in “ins” like this

"add $dst,$src"
(outs GPR64:$dst)
(ins GPR64:$src1, GPR64:$src2)

And your pattern will need to be

(set GPR64:$dst,(add GPR64:$src1,GPR64:$src2))

Then just above your instruction definition you need

let Constraints = "$src1 = $dst" in

This will tell tell register allocation that they need to be the same register.

Hi Zhang,
I am not sure this is the only, nor the best, way to do it, but in our backend we define a “fake” input operand for two operands instructions. And we add the constraint of the first input being the same register of the output:

let Constraints = “$in0 = $out” in
<(outs MyRegClass:$out), (ins MyRegClass:$in0, MyRegClass:$in1)

I guess such constraints could be all the way in your instruction classes definitions.
Hope that was clear enough.


Thanks Craig and Diogo.
I understand how this works for ALU Instructions. But how about MOV Instructions?
Let’s say the ISA is:

MOV X0,#1 // X0=1

I’m not sure about where to put the fake new operand in the instruction pattern part. For now I uses the following which got rejected with message :
Operand $op does not appear in the instruction pattern

(outs GP8:$dst)
(ins GP8:$op,i8imm:$imm)
(set GP8:$dst,(imm i8:$imm))