[LLVMdev] Multi-instruction patterns, tablegen and chains

Matthijs Kooijman matthijs at stdin.nl
Mon Nov 3 09:05:10 PST 2008

Hi all,

I'm trying some stuff with tblgen and it is doing things I didn't expect.

As for some background, I have this RD (read) instruction, which reads a value
from an external output. In our architecture, we have two types of registers:
buses and registers. The RD instructions puts its result on bus, while the
consumer of that data wants to have it in a register. To accomplish this, a
move instruction must be inserted.

My RD and MOVE instructions are simply defined as follows:

  class MontiumInst<  bits<6> op,
                      dag outs,                                                  
                      dag ins,
                      string asmstr,
                      list<dag> pattern 
                   > : Instruction 
    bits<6> opcode = op;
    dag OutOperandList = outs;
    dag InOperandList  = ins;
    let AsmString   = asmstr;                                                    
    let Pattern     = pattern;

  def RD : MontiumInst< 0x00,
                        (outs Bus:$dst),
                        (ins i32imm:$addr),
                        "$dst = rd $addr",

  def MOVE : MontiumInst< 0x00,
                          (outs DatapathReg:$dst),
                          (ins Bus:$src),
                          "$dst = $src",

In the isel input, there is a "rd" SDNode, which I'd like to turn into a RD and
a MOVE instruction. Since I can't do that in the Instruction's pattern, I added
the folowing generic Pat:

def          : Pat< (rd imm:$addr),
                    (MOVE (RD imm:$addr))

At first, this seems to work as expected. However, when I have two rd nodes in
my input, both reading from the same "address", these nodes get merged into a
single RD node. Since reads actually read from a FIFO, this should really not

Setting hasSideEffects = 1 on the RD Instruction seemed like a logical idea,
but only resulting in tblgen telling me he already inferred that. After some
discussion, it seems that the problem here is that the RD nodes don't get a
chain input and output in the selected DAG.

As a second try, I set hasCtrlDep = 1 on the RD instruction, assuming it would
ensure that RD would always use chain operands (the comment on hasCtrlDep says
"Does this instruction r/w ctrl-flow chains?"). However, this didn't help at
all. In fact, it seems that the value of hasCtrlDep is totally ignored by
tblgen. It gets assigned to an instance variable at
utils/TableGen/CodeGenInstruction.cpp:98, but that variable doesn't seem to be
used anywhere.

Some further investigation of the code turns out that EmitResultCode in
utils/TableGen/DAGISelEmitter.cpp tries to find out if an output node requires
chain operands, but gets it wrong. Around line 913, it does the following:
	Try to find the pattern belonging to the current Instruction. This is the
	first pattern listed in the Instruction definition, which does not exist for
	the above RD and Move instructions.
	If there is no such pattern, and this is the root node (MOVE in the above
	Pat), then use the pattern from the Pat node (rd imm:$addr above).

	Then, from the pattern you found, see if any node in the pattern is an
	SDNode that has the SDNPHasChain property set. If so, the current
	instruction needs chain operands.

Applying the above (slightly simplified) logic to the my Pat result
"(MOVE (RD imm:$addr))", we find the following:
	* The first node, MOVE, has no associated pattern. It is however the root
	  node, so we use "(rd imm:$addr)" as its pattern. This pattern has the
		SDNPHasChain property set, so the resulting MOVE node needs a chain.
	* The second node, RD, has no associated pattern. It is also not the root
	  node, so we can't find any pattern for it. Thus, it does not get any chain

As a result, the chain operands end up at the MOVE instruction (which really
doesn't need them) instead of at the RD instruction.

I tried fixing this by associating a pattern with the RD instruction, that has
the SDNPHasChain property set. In particular, I tried 
"(set Bus:$reg, (rd imm:$addr))". This works to some degree: The Emit function
generated by the Pat node now properly sets up the chain on the RD
instruction. However, the pattern from the RD Instruction is now matched
before the Pat node, so now the MOVE node never gets created at al...

It seems like tblgen is wrong here, and should probably just respect the
hasCtrlDep property. Alternatively, one might want to say that in the
"(MOVE (RD imm:$addr))" result dag, the RD node is to be considered the "root"
node, in the sense that it should inherit the properties of the input pattern.

Am I doing something wrong here, or is tblgen mistaken?


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20081103/70bae391/attachment.sig>

More information about the llvm-dev mailing list