Regarding Instruction definition in LLVM backend

Hi all,

My question is related to the register usage in instruction definition at file.

I have defined new Target with it Registers and instructions.

Now I need to generate an instruction like:

for the built-in function taking one constant integer argument, such as

I wondering whether it is possible to do this using only TableGen ?

I assume that I should only define a class in file.

Currently I have done the following:

in file I have defined the registers: MYREG1_NAME and
in file I have the following definitions:
def simm16 : Operand<i16> {
  let DecoderMethod= "DecodeSimm16";
  let OperandType = "OPERAND_IMMEDIATE";
class SII<bits&lt;6> op, string instr_asm, Operand Imm> :
         FI<op, (outs), (ins Imm:$val), !strconcat(instr_asm,
&quot;\t$val&quot;), [], IIAlu> {
    let rs = 0;
    let rt = 0;

def MOV : SII<0x21, "mov", simm16>;

def : TARGETPat<(int_my_builtin_function_name (imm:$val)), (MOV imm:$val)>;

I just found that the base Instruction class has Defs and Uses lists where
it is possible to pass the Registers, but actually I could not use them for
my situation.
I think that I should have Registers in a class "SII", for example like:

class SII<bits&lt;6> op, string instr_asm, list<Register> Regs, Operand Imm>
         FI<op, (outs), (ins Imm:$val), !strconcat(instr_asm,
&quot;\t$Regs->0, $Regs->1"), [], IIAlu> { /// I am not sure that I got
list elements correctly.
    let rs = 0;
    let rt = 0;

def MOV : SII<0x21, "mov", [MYREG1_NAME, MYREG2_NAME], simm16>;

but in this case there is a problem with pattern matching.

I hope to find any good ideas/advices here.

Thanks for your time,

Hi Arsen,

It looks like you're well on your way, but I'm a bit confused about
the status of your "mov" instruction. At the top you seem to be saying
it's reg -> reg, but the definition includes an unexplained immediate.

Are you trying to model something like
__builtin_my_builtin_function(0xNM) mapping to "mov rN, rM"? Or is the
"mov" more complicated than it seems?



Hi Tim,

Thank you for your response.

I need that immediate value latter to concatenate to registers' names (which
I am doing during assembly printing).

Also just Updating some status for my questioin:
I have continued with using *Defs* list. It allows me to keep Registers as
an implicit operands of /*MachineInstr*/ and later during its lowering pass
them to the /*MCInstr*/. Now seems I need only to change
*/printInstruction()/* function to Emit this instructions in appropriate
way. For that I need to change /*utils/TableGen/AsmWriterEmitter.cpp:
AsmWriterEmitter::EmitPrintInstruction*/ to generate appropriate code in
"/" file.

But I am still thinking that there should be a way to not pass the registers
as an implicit operands. So other approaches will be appreciated.


I need that immediate value latter to concatenate to registers' names (which
I am doing during assembly printing).

That really sounds like an odd implementation. Are your other
instructions more normal (i.e. proper instance of RegisterClass,
non-trivial (outs ...) and (ins ...), printing operands mostly handled
by LLVM, ...)?

If not, you really should be trying to follow that convention. This
approach just isn't going to work in LLVM. On the other hand, if they
are, what makes this MOV special? It looks like it's only that you
have a really odd intrinsic you're trying to define?

Or is it that MYREG1_NAME and MYREG2_NAME aren't your usual general
purpose registers, and actually more like system control placeholders?
AArch64, for example, has "mrs x0, TPIDR_EL0" to read the
thread-specific base address; x0 is normal, but TPIDR_EL0 isn't a
register LLVM should be tracking; it's more of an immediate with a
convenient textual form.

Either way, I think there are other ways to handle an intrinsic like
that, but we need to know more details to say what they are.



Hi Tim,

Many thanks for your thoughts.

Actually I have implemented it with the approach I choose (using Defs and
then changing the assembly printer to emit the MCInstr in an appropriate
way). And seems that works for me now.

Actually I need to have finally assembly code with

where 88 is an immediate argument value of the built-in function. This is
needed for my target which can understand this kind of registers.

Thank you again, Tim, for your time.