A few questions from a newbie

Hello, I am learning to write a new backend for LLVM and have a few simple questions.

  1. What are the differences between ‘constant’ and ‘targetconstant’, ‘globaladdress’ and ‘targetglobaladdress’? It is not clear from the document when and which should be used.

  2. On the processor I am working on, there is a ‘move reg, mem_addr’ instruction.

When I try to match it using the pattern [(set Int32Regs::reg, tglobaladdr::mem_addr)]. the code generated by tblgen cannot be compiled because there will be a switch statement that contains two cases for the ‘tglobaladdr’, one is hard-coded in by tblgen and the other is generated by tbglen following the pattern I specified. The compilation fails because of the two duplicated and conflicting cases.

When I try to match it using the pattern [(set Int32Regs::reg, globaladdr::mem_addr)], the corresponding DAG node generated does not take the mem_addr as an input. As a matter of fact, it takes itself as an input and forms cycle.

I am not sure if I explain the problems clearly. I can certainly provide more information if needed.

Thank you in advance.

P.B.

Hello, I am learning to write a new backend for LLVM and have a few simple questions.

Hi Peter,

I am a newbie too, but I have recently dealt with the same issues.

1) What are the differences between 'constant' and 'targetconstant', 'globaladdress' and 'targetglobaladdress'? It is not clear from the document when and which should be used.

The target* variants are 'done' and will not be changed further by the instruction selection. After instruction selection, everything should be converted to the target* variants.

2) On the processor I am working on, there is a 'move reg, mem_addr' instruction.

When I try to match it using the pattern [(set Int32Regs::reg, tglobaladdr::mem_addr)]. the code generated by tblgen cannot be compiled because there will be a switch statement that contains two cases for the 'tglobaladdr', one is hard-coded in by tblgen and the other is generated by tbglen following the pattern I specified. The compilation fails because of the two duplicated and conflicting cases.

This happened to me too. I stole a solution from the other targets - create a wrapper node:

def BfinWrapper: SDNode<"BfinISD::Wrapper", SDTIntUnaryOp>;

Then custom lower ISD::GlobalAddress, converting it to a wrapped TargetGlobalAddress:

SDValue
BlackfinTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG)
{
   DebugLoc DL = Op.getDebugLoc();
   GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();

   Op = DAG.getTargetGlobalAddress(GV, MVT::i32);
   return DAG.getNode(BfinISD::Wrapper, DL, MVT::i32, Op);
}

Now you can pattern match on the wrapper:

def : Pat<(BfinWrapper (i32 tglobaladdr:$addr)),
           (LOAD32imm tglobaladdr:$addr)>;

If you think this is overly complicated, I agree.
Does anybody know why this is necessary?

/jakob

Hi Jacob, thank you for your reply.

Your suggestion works! But instead of using the Pat<>, I am using

def MOVE_ADDR : MYInst<(outs Int32Regs:$dst), (ins i32mem:$a),
“move $dst, $a;”,
[(set Int32Regs:$dst, (Wrapper tglobaladdr:$a))]>;

I don’t quite understand what the semantics of Pat in general. Could you please explain what

def : Pat<(BfinWrapper (i32 tglobaladdr:$addr)),
(LOAD32imm tglobaladdr:$addr)>;

means?

And I totally agree it would be better if someone can explain why the Wrapper is needed here.

Regards,

P.B.

Peter Bacon <peter.b.bacon@gmail.com> writes:

Your suggestion works! But instead of using the Pat<>, I am using

def MOVE_ADDR : MYInst<(outs Int32Regs:$dst), (ins i32mem:$a),
"move $dst, $a;",
[(set Int32Regs:$dst, (Wrapper tglobaladdr:$a))]>;

This is fine.

I don't quite understand what the semantics of Pat in general. Could you please explain what

def : Pat<(BfinWrapper (i32 tglobaladdr:$addr)),
(LOAD32imm tglobaladdr:$addr)>;

means?

It means the same as the pattern you wrote above. You could also have
written:

def MOVE_ADDR : MYInst<(outs Int32Regs:$dst), (ins i32mem:$a),
"move $dst, $a;", >;

def : Pat<(Wrapper tglobaladdr:$a), (MOVE_ADDR i32mem:$a)>;

Pat<A,B> simply means "replace A by B" in the DAG. It is useful if you
have more than one pattern for a single instruction, or if you want to
use multiple instructions in a pattern replacement.

This means, in general terms, "when I see the pattern (BfinWrapper
(i32 tglobaladdr:$addr)), substitute that with (LOAD32imm
tglobaladdr:$addr)".

-bw