<div dir="ltr">To the best of my knowledge, having 2 explicit physical registers(in your case A and F) in the output of an instruction isn't supported correctly by tablegen and never has been. Maybe it previously appeared to work well enough to pass build?<div><br></div><div>This is why X86 has the pattern commented out here and implements custom handling in X86ISelDAGToDAG.cpp.<div><br></div><div><div>// EAX,EDX = EAX*GR32</div><div>let Defs = [EAX,EDX,EFLAGS], Uses = [EAX], hasSideEffects = 0 in</div><div>def MUL32r : I<0xF7, MRM4r, (outs),  (ins GR32:$src),</div><div>               "mul{l}\t$src",</div><div>               [/*(set EAX, EDX, EFLAGS, (X86umul_flag EAX, GR32:$src))*/]>,</div><div>               OpSize32, Sched<[WriteIMul]>;</div><div>// RAX,RDX = RAX*GR64</div><div>let Defs = [RAX,RDX,EFLAGS], Uses = [RAX], hasSideEffects = 0 indef MUL64r : RI<0xF7, MRM4r, (outs), (ins GR64:$src),</div><div>                "mul{q}\t$src",</div><div>                [/*(set RAX, RDX, EFLAGS, (X86umul_flag RAX, GR64:$src))*/]>,</div><div>                Sched<[WriteIMul64]>;</div></div><div><br></div><div><br></div><div>I vaguely recall trying to fix tablegen probably at least 5 years ago, but didn't succeed. Looking back at the code now I can tell you the two places in DAGISelMatcherGen.cpp that call HasOneImplicitDefWithKnownVT are definitely unable to handle multiple implicit def destinations in a pattern.</div><div><br></div><div><div><div dir="ltr" class="gmail_signature">~Craig</div></div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jul 9, 2018 at 9:30 PM Michael Stellmann via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
I'm trying to revive jacobly0's Z80 back-end (from <br>
<a href="https://github.com/jacobly0/llvm-z80" rel="noreferrer" target="_blank">https://github.com/jacobly0/llvm-z80</a>) and build it with a current <br>
version of LLVM.<br>
<br>
Apart from some interface changes, I'm stuck at building the tables. <br>
Specifically, the generation of the DAG instruction selector causes an <br>
assertion in the table generator:<br>
<br>
     Assertion failed: Ops.size() >= NumSrcResults && "Didn't provide <br>
enough results"<br>
<br>
I tried to fix the problem by searched in the documentation and in other <br>
table sources, but to no avail. Even stepping through that code in the <br>
debugger (MatcherGen::EmitResultCode()) didn't help me to find the cause <br>
of the problem. The instruction tables description are quite unique in <br>
all the officially supported CPU models, I couldn't find any similar <br>
code that could help me figuring out what is going wrong.<br>
<br>
So I isolated the table sources to a minimum of two simple <br>
base-instructions and attached these for reproduction of the problem <br>
(not sure if the attachment gets through).<br>
<br>
The table generation is done with:<br>
<br>
     llvm-tblgen -gen-dag-isel -I=<path-to-llvm-include> -o=out.inc Z80.td<br>
<br>
The first instruction in Z80InstrInfo.td is a unary instruction, that <br>
does a rotate left of a byte in memory, resulting in the leftmost bit <br>
being placed in the Carry flag - and changing the memory contents at the <br>
pointer's address (in Z80: "RLC (HL)", I expect).<br>
The table generation completes without errors with just this instruction <br>
(by commenting the last line in Z80InstrInfo.td).<br>
<br>
The second one is a binary instruction, adding the contents of a pointer <br>
and a register, with results in register A and F (Z80: "ADD A,(HL)").<br>
<br>
A is an 8-bit register. The Z80 ALU can only do 8 bit arithmetic with <br>
that register and another param. The two instructions don't seem to <br>
require a specific register for the address in the table class, so the <br>
RegisterInfo table is not defined so far in the minimized version<br>
<br>
The problem is in Z80InstrInfo.td, in the following section of <br>
"BinOp8RF", which is used by the "defm" line that generates the "add" <br>
instruction pattern:<br>
<br>
     multiclass BinOp8RF<Prefix prefix, bits<3> opcode, string mnemonic,<br>
                         bit compare = 0> {<br>
       let isCompare = compare, Defs = [A, F], Uses = [A] in {<br>
         def 8ap : I8 <prefix, {0b10, opcode, 0b110}, mnemonic, "\ta, <br>
$src", "",<br>
                       (outs), (ins   ptr:$src),<br>
                       [(set A, F,<br>
                            (Z80add_flag<br>
                                 A, (i8 (load   iPTR:$src))))]>;<br>
       }<br>
     }<br>
<br>
and the parameters:<br>
<br>
     def SDTBinOpRF  : SDTypeProfile<2, 2, [SDTCisInt<0>,<br>
                                            SDTCisFlag<1>,<br>
                                            SDTCisSameAs<2, 0>,<br>
                                            SDTCisSameAs<3, 0>]>;<br>
<br>
     def Z80add_flag      : SDNode<"Z80ISD::ADD",     SDTBinOpRF, <br>
[SDNPCommutative]>;<br>
<br>
<br>
The unary instruction builds fine, which can be checked by commenting <br>
out the generation of the binary instruction in the last line of the <br>
attached Z80InstrInfo.td.<br>
<br>
The log in Github indicates that this section was present for over a <br>
year, so I assume that it did work at some time in the past.<br>
<br>
My attempts to fixing the instruction failed with other errors, pointing <br>
specifically to the specific problems I introduced with the change, e.g. <br>
parameter number mismatch or wrong type, so above (and attached) is the <br>
unmodified version.<br>
<br>
Any help is appreciated!<br>
<br>
Michael<br>
<br>
<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>