Using `smullohi` in TableGen patterns

I’m hitting TableGen errors trying to match the smullohi <lhs> <rhs> node in TableGen.

smullohi returns two results, which is the problem. I am not sure how to match against multiple results. The only other nodes to return two operands are umullohi, udivrem, and sdivrem. There are no examples of these in TableGen in tree.

The closest I can get is this:

        set (R1, R0, (umullohi GPR8:$lhs, GPR8:$rhs))

Which fails:

        Assertion failed: (Ops.size() >= NumSrcResults && "Didn't provide enough results"), function EmitResultCode, file /Users/dylanmckay/projects/llvm/avr-llvm/utils/TableGen/DAGISelMatcherGen.cpp, line 989.

0  libLLVMSupport.dylib     0x0000000108e8c47e llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 46

1  libLLVMSupport.dylib     0x0000000108e8c8c9 PrintStackTraceSignalHandler(void*) + 25

2  libLLVMSupport.dylib     0x0000000108e89069 llvm::sys::RunSignalHandlers() + 425

3  libLLVMSupport.dylib     0x0000000108e8cc29 SignalHandler(int) + 345

4  libsystem_platform.dylib 0x00007fff947f5eaa _sigtramp + 26

5  libLLVMSupport.dylib     0x0000000108eafec9 llvm::sys::DynamicLibrary::Invalid + 9361

6  libLLVMSupport.dylib     0x0000000108e8c8eb raise + 27

7  libLLVMSupport.dylib     0x0000000108e8c9a2 abort + 18

8  libLLVMSupport.dylib     0x0000000108e8c981 __assert_rtn + 129

9  llvm-tblgen              0x000000010893f524 (anonymous namespace)::MatcherGen::EmitResultCode() + 964

10 llvm-tblgen              0x000000010893e12f llvm::ConvertPatternToMatcher(llvm::PatternToMatch const&, unsigned int, llvm::CodeGenDAGPatterns const&) + 143

11 llvm-tblgen              0x0000000108927ca5 (anonymous namespace)::DAGISelEmitter::run(llvm::raw_ostream&) + 3205

12 llvm-tblgen              0x0000000108926fd6 llvm::EmitDAGISel(llvm::RecordKeeper&, llvm::raw_ostream&) + 54

13 llvm-tblgen              0x0000000108a6dfc8 (anonymous namespace)::LLVMTableGenMain(llvm::raw_ostream&, llvm::RecordKeeper&) + 328

14 libLLVMTableGen.dylib    0x0000000108fd7cb1 llvm::TableGenMain(char*, bool (*)(llvm::raw_ostream&, llvm::RecordKeeper&)) + 2385

15 llvm-tblgen              0x0000000108a6de5b main + 91

16 libdyld.dylib            0x00007fff946fe5ad start + 1

As far as I know, you cannot define a tablegen pattern with multiple results, and need to use C++ matching. I’m kind of surprised there are defined td nodes for these.

-Matt

As far as I know, you cannot define a tablegen pattern with multiple results, and need to use C++ matching. I’m kind of surprised there are defined td nodes for these.

Yes they were added a while ago, but never used.

If I write a C++ matcher, will the register allocator work correctly? The multiplication instruction I’m working with always writes the result to registers R1 and R0, but if that logic is in C++, how will the regallocator know?

As far as I know, you cannot define a tablegen pattern with multiple results, and need to use C++ matching. I’m kind of surprised there are defined td nodes for these.

Yes they were added a while ago, but never used.

I vaguely remember some patches to add support for multiple results, but I’m not sure this was ever finished.

If I write a C++ matcher, will the register allocator work correctly? The multiplication instruction I’m working with always writes the result to registers R1 and R0, but if that logic is in C++, how will the regallocator know?

The pattern isn’t really related to the machine instruction’s operand definition. The multiple operands will each be defs.

-Matt

If I write a C++ matcher, will the register allocator work correctly? The
multiplication instruction I'm working with always writes the result to
registers `R1` and `R0`, but if that logic is in C++, how will the
regallocator know?

You'd add extra CopyFromReg nodes, glued[1] to your multiplication
node. The values produced by the CopyFromReg nodes are what other
users should actually be using[2]. x86 has similar hard-coded
registers on its multiplication operations, I believe. Try "llc
-view-sched-dags ..." to see the kind of thing you should be
producing.

Cheers.

Tim.

[1] Glue is represented by producing/consuming a value of type MVT::Glue.
[2] You may well have to manually call ReplaceAllUsesOfValueWith after
creating them to make that happen.

You’d add extra CopyFromReg nodes, glued[1] to your multiplication node

Thanks makes a lot of sense, thanks Tim!