TableGen patterns with multiple outputs

Are multi-output patterns in TableGen supposed to work, or is that a known limitation in the current implementation?

If I have TableGen code like the following…

1242 def SDTTestNode : SDTypeProfile<2, 1, [SDTCisSameAs<0, 1>]>;
1243 def TestNode : SDNode<“NVPTXISD::TestNode”, SDTTestNode>;
1245 def MyTestNode : NVPTXInst<(outs Int32Regs:$dst0, Int32Regs:$dst1),
1246 (ins Int32Regs:$a),
1247 “test $dst0, $dst1, $a;”,
1248 [(set Int32Regs:$dst0, Int32Regs:$dst1, (TestNode Int32Regs:$a))]>;

… TableGen crashes with the following stack trace:

#0 0x00007fff8f372212 in __pthread_kill ()
#1 0x00007fff8dc0eaf4 in pthread_kill ()
#2 0x00000001003a978b in raise (sig=6) at
#3 0x00000001003a9842 in abort () at
#4 0x00000001003a9821 in __assert_rtn (func=0x1003d0d14 “operator[]”, file=0x1003b169e “/Users/jholewinski/projects/llvm/src/llvm/include/llvm/ADT/SmallVector.h”, line=139, expr=0x1003b16e7 “begin() + idx < end()”) at
#5 0x00000001000ca394 in llvm::SmallVectorTemplateCommon<llvm::EEVT::TypeSet, void>::operator[] (this=0x10384fed0, idx=1) at SmallVector.h:139
#6 0x00000001000c965b in llvm::TreePatternNode::getExtType (this=0x10384fed0, ResNo=1) at CodeGenDAGPatterns.h:349
#7 0x00000001000bd615 in llvm::CodeGenDAGPatterns::ParseInstructions (this=0x7fff5fbff0b0) at /Users/jholewinski/projects/llvm/src/llvm/utils/TableGen/CodeGenDAGPatterns.cpp:2782
#8 0x00000001000b7143 in llvm::CodeGenDAGPatterns::CodeGenDAGPatterns (this=0x7fff5fbff0b0, R=@0x7fff5fbff670) at /Users/jholewinski/projects/llvm/src/llvm/utils/TableGen/CodeGenDAGPatterns.cpp:2077
#9 0x00000001000b6a3d in llvm::CodeGenDAGPatterns::CodeGenDAGPatterns (this=0x7fff5fbff0b0, R=@0x7fff5fbff670) at /Users/jholewinski/projects/llvm/src/llvm/utils/TableGen/CodeGenDAGPatterns.cpp:2091
#10 0x000000010024cd15 in InstrInfoEmitter (this=0x7fff5fbff0a8, R=@0x7fff5fbff670) at /Users/jholewinski/projects/llvm/src/llvm/utils/TableGen/InstrInfoEmitter.cpp:39
#11 0x0000000100248e8d in InstrInfoEmitter (this=0x7fff5fbff0a8, R=@0x7fff5fbff670) at /Users/jholewinski/projects/llvm/src/llvm/utils/TableGen/InstrInfoEmitter.cpp:39
#12 0x0000000100248e36 in llvm::EmitInstrInfo (RK=@0x7fff5fbff670, OS=@0x7fff5fbff518) at /Users/jholewinski/projects/llvm/src/llvm/utils/TableGen/InstrInfoEmitter.cpp:420
#13 0x00000001002d0930 in LLVMTableGenMain (OS=@0x7fff5fbff518, Records=@0x7fff5fbff670) at /Users/jholewinski/projects/llvm/src/llvm/utils/TableGen/TableGen.cpp:106
#14 0x00000001002e8385 in llvm::TableGenMain (argv0=0x7fff5fbffa88 “/Users/jholewinski/projects/llvm/build/bin/llvm-tblgen”, MainFn=0x1002d0880 ) at /Users/jholewinski/projects/llvm/src/llvm/lib/TableGen/Main.cpp:117
#15 0x00000001002d0864 in main (argc=11, argv=0x7fff5fbff8f8) at /Users/jholewinski/projects/llvm/src/llvm/utils/TableGen/TableGen.cpp:181

The fault occurs in CodeGenDAGPatterns.cpp:

2781 for (unsigned i = 0; i != NumResults; ++i)
2782 ResultPattern->setType(i, Res0Node->getExtType(i));

Res0Node has only 1 type, but it is expected to have 2.

Looking at the X86 back-end code, it looks like there do exist multi-output instructions, but they all use physical (implicit) registers for the second destination, not arbitrary register types. And if I change the second destination to be a certain physical register, this problem goes away in my code. Is this just not a supported case currently? Or am I doing something wrong?

This is my first time looking into the TableGen internals, so I can’t spot anything obviously wrong with the TableGen tool code.

Are multi-output patterns in TableGen supposed to work, or is that a known limitation in the current implementation?

It is a known limitation. You have to write C++ code to match patterns with multiple outputs.

Thanks for the info. Is this on someone’s list of things to do?

It has been something we’ve talked about for years, but I’m not aware of anyone working on it right now.

I may look at this if I get some spare cycles. We have some use-cases for
this, and converting custom C++ selection to TableGen rules would be nice.
Though its not critical, so I'm not sure when I'd get to it.