Hello everyone! I’m implementing a custom target in LLVM’s TableGen and ran into two related issues when defining my instructions:
I have instructions where the destination and source are the same register (e.g. an increment). How do I tell TableGen that $dst and $src are actually the same operand, rather than two independent register operands?
Some of my instructions take a single register index but that index refers to a general-purpose register (GPR) and a floating-point register (FPR), like (ins GPR:$src, FPR:$src).
Any advice or examples of how to fold $dst and $src into one physical operand and to let a single index use two register classes, would be greatly appreciated!
Use let Constraints = "$dst = $src" on the instruction.
Such constraints are poorly modeled in LLVM. The only built-in way is to define a superregister containing both GPR and FPR as subregisters. See RegisterTuples.
Thank you very much for your reply! I have one more question. Am I right in assuming that multiple output operands are fully supported? If so, how can I create a pattern that returns multiple registers if it is not an intrinsic?
When it comes to writing patterns, this is fully supported only for patterns embedded into instruction definitions (let Pattern = ...). Top-level patterns (def Pat : ...) have very limited support: they require that the source and destination results match in order and belong to the same node/instruction.
Example:
def MyInstr {
let OutOperandList = (outs RC:$dst1, RC:$dst2);
let InOperandList = (ins RC:$src1, RC:$src2);
let Pattern = [(set RC:$dst2, RC:$dst1, (divrem $src1, $src2))];
}
where divrem has two results in reverse order compared to your instruction.
If you need more than one pattern or you don’t like embedded patterns you will have to write custom selection code in C++.
I’m sorry, but I do not understand how to create a pattern for dags with two or more different output branches (It is not intuitive how to process all these nodes in general):
$src1 $src2
\ /
add
/ \
abs abs
| |
$dst1 neg
|
$dst2 let Pattern = [(set GPR:$dst1, GPR:$dst2, (???))];.
I’m not sure I understand the question. Instruction semantics is opaque to LLVM. It only knows about inputs/outputs and properties like hasSideEffects etc.
Alternatively, you can also use Complex Patterns and implement the Cpp function to match it. I recommend “LLVM Code Generation” by Quentin Colombet, i just started it and it cleared up a lot of my confusion about this