Gabriel Hjort Åkerlund via llvm-dev
2020-Jun-08 15:13 UTC
[llvm-dev] Nested instruction patterns rejected by GlobalISel when having registers in Defs
Hi Daniel,
Thanks for replying; I was hoping to get in touch with you on this issue.
I had a look at how SelectionIDAG does it when generating the matcher table,
and it does consider the implicit defs as additional output. Here is the
match table generated for the pattern:
/* 0*/ OPC_CheckOpcode, TARGET_VAL(ISD::SIGN_EXTEND),
/* 3*/ OPC_MoveChild0,
/* 4*/ OPC_CheckOpcode, TARGET_VAL(ISD::SHL),
/* 7*/ OPC_MoveChild0,
/* 8*/ OPC_CheckOpcode, TARGET_VAL(ISD::ANY_EXTEND),
/* 11*/ OPC_RecordChild0, // #0 = $src
/* 12*/ OPC_CheckChild0Type, MVT::i16,
/* 14*/ OPC_MoveParent,
/* 15*/ OPC_RecordChild1, // #1 = $imm
/* 16*/ OPC_MoveChild1,
/* 17*/ OPC_CheckOpcode, TARGET_VAL(ISD::Constant),
/* 20*/ OPC_CheckPredicate, 0, // Predicate_Imm_17_31_i16
/* 22*/ OPC_CheckType, MVT::i16,
/* 24*/ OPC_MoveParent,
/* 25*/ OPC_CheckType, MVT::i32,
/* 27*/ OPC_MoveParent,
/* 28*/ OPC_CheckType, MVT::i40,
/* 30*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::IMPLICIT_DEF), 0,
MVT::i40, 0/*#Ops*/, // Results = #2
/* 36*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::IMPLICIT_DEF), 0,
MVT::i32, 0/*#Ops*/, // Results = #3
/* 42*/ OPC_EmitInteger, MVT::i32, OurTarget::hi16, // Results = #4
/* 45*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::INSERT_SUBREG), 0,
MVT::i32, 3/*#Ops*/, 3, 0, 4, // Results = #5
/* 54*/ OPC_EmitNode1, TARGET_VAL(OurTarget::clearLo32_pseudo), 0,
MVT::i32, 1/*#Ops*/, 5, // Results = #6
/* 61*/ OPC_EmitInteger, MVT::i16, 0,
/* 64*/ OPC_EmitRegister, MVT::i16, 0 /*zero_reg*/,
/* 67*/ OPC_EmitInteger, MVT::i16, 0,
/* 70*/ OPC_EmitNode2, TARGET_VAL(OurTarget::shfts_a32_imm7), 0,
MVT::i32, MVT::i16, 5/*#Ops*/, 6, 1, 7, 8, 9, // Results #10 #11
/* 82*/ OPC_EmitInteger, MVT::i32, OurTarget::acc,
/* 85*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::INSERT_SUBREG), 0,
MVT::i40, 3/*#Ops*/, 2, 10, 12, // Results = #13
/* 94*/ OPC_EmitInteger, MVT::i16, 0,
/* 97*/ OPC_EmitRegister, MVT::i16, 0 /*zero_reg*/,
/* 100*/ OPC_EmitInteger, MVT::i16, 0,
/* 103*/ OPC_MorphNodeTo1, TARGET_VAL(OurTarget::sext_a32), 0,
MVT::i40, 4/*#Ops*/, 13, 14, 15, 16, ...
The line of interest here is the one below /* 70 */. There, we can see
that the instruction produces two results of type MVT::i32 (the value
produced by the instruction) respectively MVT::i16 (the CCReg updated by the
instruction). These are labeled as results #10 respectively #11. Looking at
operand identifiers after /*#Ops*/, we can see that only #10 is used by the
rest of the resulting pattern (by INSERT_SUBREG), which is as intended.
However, in the destination pattern declared in the *.td file, there is no
information pertaining to which of the results should be used by the parent
node. Since only tree-shaped patterns are allowed, SelectionIDAG must
somehow decide which of the results are to be used by the parent node. And
this decision is taken at lines 869-870 in DAGISelMatcherGen.cpp:
...
unsigned FinalNumOps = InstOps.size() + NumSubOps;
while (InstOps.size() < FinalNumOps) {
const TreePatternNode *Child = N->getChild(ChildNo);
unsigned BeforeAddingNumOps = InstOps.size();
EmitResultOperand(Child, InstOps);
assert(InstOps.size() > BeforeAddingNumOps && "Didn't
add any
operands");
// If the operand is an instruction and it produced multiple results,
just
// take the first one.
if (!Child->isLeaf() &&
Child->getOperator()->isSubClassOf("Instruction"))
InstOps.resize(BeforeAddingNumOps+1);
++ChildNo;
}
...
In other words, if a child produces more than one result SelectionIDAG
always takes the first result. Those two lines originate from a patch by
Chris Lattner (r99725), so presumably this is the correct way of doing it.
If GlobalISel were to do the same, it would solve the issue I'm having with
our patterns.
Best regards,
Gabriel
_____
From: Daniel Sanders <daniel_l_sanders at apple.com>
Sent: Friday, June 5, 2020 9:02 PM
To: Quentin Colombet <qcolombet at apple.com>
Cc: Dominik Montada <dominik.montada at hightec-rt.com>; Gabriel Hjort
Åkerlund
<gabriel.hjort.akerlund at ericsson.com>; llvm-dev at lists.llvm.org
<llvm-dev at lists.llvm.org>
Subject: Re: [llvm-dev] Nested instruction patterns rejected by GlobalISel
when having registers in Defs
The implicit defs don't participate much in the patterns. For the most part
it's just read into CodeGenInstruction::ImplicitDefs and then GlobalISel
gathers and adds them all at the end. I think I do see the code Gabriel is
referring to though.
GetNumNodeResults() has:
if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo())
!=MVT::Other)
++NumDefsToAdd;
and ultimately this VT gets into Types via UpdateNodeType(). I have no idea
why this code does this as I don't really see why the VT matters to how you
treat an implicit def. This code dates back to 2010 (r99726) and that commit
called it 'funky logic' so it's unlikely that we'll find someone
that
remembers it.
Does your CCReg need to have a specific type? If not, then you could make it
MVT::Other and the problem should go away.
Have you looked into how DAGISel supports these patterns? This code is
common between DAGISel and GlobalISel so given that DAGISel works it must be
doing something to handle this that's missing from GlobalISel.
On 5 Jun 2020, at 11:02, Quentin Colombet < <mailto:qcolombet at
apple.com>
qcolombet at apple.com> wrote:
+ Daniel who knows the most about the table gen importer
On Jun 5, 2020, at 12:48 AM, Dominik Montada via llvm-dev <
<mailto:llvm-dev at lists.llvm.org> llvm-dev at lists.llvm.org> wrote:
Hi Gabriel,
Your comment made me take a look at our instruction definitions and patterns
in a little bit more detail. And while we do use nested patterns with
INSERT_SUBREG, apparently none of those patterns use instructions with
implicit-defs. Sorry for misleading you there by a wrong assumption on my
part.
However, I still find it strange that TableGen should reject such a pattern.
I'm really not sure if this is simply an overlooked use-case or if there is
some real reasoning behind this logic. If it were an actual output register
I could understand it, but since this is an implicit one it should not
impact the pattern in my opinion.
Sorry for not being able to help out with the actual problem after all!
Cheers,
Dominik
Am 04.06.20 um 15:06 schrieb Gabriel Hjort Åkerlund:
Hi Dominik,
Thanks for your reply.
In my case, the Defs is the cause of the problem. Or rather, it is part of
the problem, because when I remove it from the instruction TableGen gives me
a different error message which concerns a part which is deeper into the
pattern tree, so at least it is able to proceed beyond that part of the
pattern. I have also stepped TableGen inside gdb and verified that having
Defs causes GlobalISel to include CCReg in the Types field of the
TreePatternNode corresponding to the instruction, which is what GlobalISel
looks at to subsequently reject the pattern on basis that the instruction
produces multiple results.
But from your comment, I take it that the Defs field should never be
considered actual output, is that correct? If so, I find it strange that
CodeGenDAGPatterns, which parses the patterns, takes the CCReg into
consideration as additional results. I am tempted to modify that part of the
code, but maybe Im missing some invariant thats not immediately evident
Cheers,
Gabriel
From: Dominik Montada <mailto:dominik.montada at hightec-rt.com>
<dominik.montada at hightec-rt.com>
Sent: den 4 juni 2020 14:51
To: <mailto:llvm-dev at lists.llvm.org> llvm-dev at lists.llvm.org
Cc: Gabriel Hjort Åkerlund <mailto:gabriel.hjort.akerlund at
ericsson.com>
<gabriel.hjort.akerlund at ericsson.com>
Subject: Re: [llvm-dev] Nested instruction patterns rejected by GlobalISel
when having registers in Defs
Hi Gabriel,
I'm working on a downstream target which uses GlobalISel and we have many
patterns with instructions that also define a system register as a
side-effect and use them without any problem. Since CCReg is not an actual
output of the instruction, but an implicit definition, GlobalISel should
have no trouble with it, so I'm guessing your problem lies somewhere. Have
you tried running the tablegen command manually and looked at the output
there?
The command is llvm-tblgen -gen-global-isel <couple of -I flags>
<your_target>.td --write-if-changed --warn-on-skipped-patterns
I can't tell you exactly what -I flags you'll need but if you run ninja
in
verbose mode or look at the ninja build log, you should be able to see what
is being used.
Word of caution however: sometimes TableGen gives you a very clear error
message indicating what is wrong, sometimes it gives you a very cryptic
error message. And sometimes it doesn't even give you that and behave as if
everything is a-ok while it still hasn't included your pattern. I have lost
countless hours trying to debug TableGen patterns with GlobalISel and
there's still a lot of stuff that GlobalISel unfortunately does not support
yet in TableGen. So be prepared to write some C++ code for the unsupported
cases for the moment.
Cheers,
Dominik
Am 04.06.20 um 14:34 schrieb Gabriel Hjort Åkerlund via llvm-dev:
Hi,
I am in the process of porting our target to GlobalISel, and have
encountered a problem. Nearly all instructions in our instruction set make
modifications to a CC register, and hence are defined as follows:
let ..., Defs = [CCReg] in
def shfts_a32_imm7: Instruction<(outs OurRC:$dst), ...>;
Whats more, many of these instructions have patterns where the instruction
itself appears inside a nested tree, e.g.:
def Pat<(source pattern ...),
(sext_a32 (INSERT_SUBREG (...), (shfts_a32_imm7 OurRC:$src,
Imm7:$imm), ...>;
Now to the problem: When TableGen processes the instruction above, it
includes the CCReg in the Defs field along with the registers appearing in
outs, thereby indicating that shfts_a32_imm7 produces two results.
Currently, the GlobalISel-backend in TableGen requires that nested
instructions appearing in the output pattern produce exactly one result.
Consequently, TableGen rejects many of our patterns. But in reality, the
instruction really only produces a single result and therefore this pattern
should be allowed.
So I wonder, how should registers appear in Defs be treated? Are they equal
to those appearing in outs, and therefore interchangeable, or is it valid to
disambiguate between them and therefore modify TableGen to only consider
outs as the result of interest when processing the patterns?
Gabriel Hjort Åkerlund
_______________________________________________
LLVM Developers mailing list
<mailto:llvm-dev at lists.llvm.org> llvm-dev at lists.llvm.org
<https://protect2.fireeye.com/v1/url?k=52e18446-0c413e28-52e1c4dd-86b1886cfa
64-f424e731a80348bd&q=1&e=238953c8-f0ec-4510-8c97-620bfb03d5be&u=https%3A%2F
%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-dev>
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
--
----------------------------------------------------------------------
Dominik Montada Email:
<mailto:dominik.montada at hightec-rt.com> dominik.montada at
hightec-rt.com
HighTec EDV-Systeme GmbH Phone: +49 681 92613 19
Europaallee 19 Fax: +49-681-92613-26
D-66113 Saarbrücken WWW:
<https://protect2.fireeye.com/v1/url?k=a0228059-fe823a37-a022c0c2-86b1886cfa
64-48b7aa6978940111&q=1&e=238953c8-f0ec-4510-8c97-620bfb03d5be&u=http%3A%2F%
2Fwww.hightec-rt.com%2F> http://www.hightec-rt.com
Managing Director: Vera Strothmann
Register Court: Saarbrücken, HRB 10445, VAT ID: DE 138344222
This e-mail may contain confidential and/or privileged information. If
you are not the intended recipient please notify the sender immediately
and destroy this e-mail. Any unauthorised copying, disclosure or
distribution of the material in this e-mail is strictly forbidden.
---
--
----------------------------------------------------------------------
Dominik Montada Email:
<mailto:dominik.montada at hightec-rt.com> dominik.montada at
hightec-rt.com
HighTec EDV-Systeme GmbH Phone: +49 681 92613 19
Europaallee 19 Fax: +49-681-92613-26
D-66113 Saarbrücken WWW:
<https://protect2.fireeye.com/v1/url?k=b7cd53d5-e96de9bb-b7cd134e-861d41abac
e8-5636b949d44c6f9b&q=1&e=9aff5cfa-72fd-4986-af7c-78b27f9ea1e8&u=http%3A%2F%
2Fwww.hightec-rt.com%2F> http://www.hightec-rt.com
Managing Director: Vera Strothmann
Register Court: Saarbrücken, HRB 10445, VAT ID: DE 138344222
This e-mail may contain confidential and/or privileged information. If
you are not the intended recipient please notify the sender immediately
and destroy this e-mail. Any unauthorised copying, disclosure or
distribution of the material in this e-mail is strictly forbidden.
---
_______________________________________________
LLVM Developers mailing list
<mailto:llvm-dev at lists.llvm.org> llvm-dev at lists.llvm.org
<https://protect2.fireeye.com/v1/url?k=b3d033f0-ed70899e-b3d0736b-861d41abac
e8-91f0c9908116c6fb&q=1&e=9aff5cfa-72fd-4986-af7c-78b27f9ea1e8&u=https%3A%2F
%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-dev>
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20200608/a94c50e5/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 6320 bytes
Desc: not available
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20200608/a94c50e5/attachment-0001.bin>
Daniel Sanders via llvm-dev
2020-Jun-09 18:21 UTC
[llvm-dev] Nested instruction patterns rejected by GlobalISel when having registers in Defs
> On 8 Jun 2020, at 08:13, Gabriel Hjort Åkerlund <gabriel.hjort.akerlund at ericsson.com> wrote: > > Hi Daniel, > > Thanks for replying; I was hoping to get in touch with you on this issue. > > I had a look at how SelectionIDAG does it when generating the matcher table, and it does consider the implicit defs as additional output. Here is the match table generated for the pattern: > > /* 0*/ OPC_CheckOpcode, TARGET_VAL(ISD::SIGN_EXTEND), > /* 3*/ OPC_MoveChild0, > /* 4*/ OPC_CheckOpcode, TARGET_VAL(ISD::SHL), > /* 7*/ OPC_MoveChild0, > /* 8*/ OPC_CheckOpcode, TARGET_VAL(ISD::ANY_EXTEND), > /* 11*/ OPC_RecordChild0, // #0 = $src > /* 12*/ OPC_CheckChild0Type, MVT::i16, > /* 14*/ OPC_MoveParent, > /* 15*/ OPC_RecordChild1, // #1 = $imm > /* 16*/ OPC_MoveChild1, > /* 17*/ OPC_CheckOpcode, TARGET_VAL(ISD::Constant), > /* 20*/ OPC_CheckPredicate, 0, // Predicate_Imm_17_31_i16 > /* 22*/ OPC_CheckType, MVT::i16, > /* 24*/ OPC_MoveParent, > /* 25*/ OPC_CheckType, MVT::i32, > /* 27*/ OPC_MoveParent, > /* 28*/ OPC_CheckType, MVT::i40, > /* 30*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::IMPLICIT_DEF), 0, > MVT::i40, 0/*#Ops*/, // Results = #2 > /* 36*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::IMPLICIT_DEF), 0, > MVT::i32, 0/*#Ops*/, // Results = #3 > /* 42*/ OPC_EmitInteger, MVT::i32, OurTarget::hi16, // Results = #4 > /* 45*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::INSERT_SUBREG), 0, > MVT::i32, 3/*#Ops*/, 3, 0, 4, // Results = #5 > /* 54*/ OPC_EmitNode1, TARGET_VAL(OurTarget::clearLo32_pseudo), 0, > MVT::i32, 1/*#Ops*/, 5, // Results = #6 > /* 61*/ OPC_EmitInteger, MVT::i16, 0, > /* 64*/ OPC_EmitRegister, MVT::i16, 0 /*zero_reg*/, > /* 67*/ OPC_EmitInteger, MVT::i16, 0, > /* 70*/ OPC_EmitNode2, TARGET_VAL(OurTarget::shfts_a32_imm7), 0, > MVT::i32, MVT::i16, 5/*#Ops*/, 6, 1, 7, 8, 9, // Results = #10 #11 > /* 82*/ OPC_EmitInteger, MVT::i32, OurTarget::acc, > /* 85*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::INSERT_SUBREG), 0, > MVT::i40, 3/*#Ops*/, 2, 10, 12, // Results = #13 > /* 94*/ OPC_EmitInteger, MVT::i16, 0, > /* 97*/ OPC_EmitRegister, MVT::i16, 0 /*zero_reg*/, > /* 100*/ OPC_EmitInteger, MVT::i16, 0, > /* 103*/ OPC_MorphNodeTo1, TARGET_VAL(OurTarget::sext_a32), 0, > MVT::i40, 4/*#Ops*/, 13, 14, 15, 16, ... > > The line of interest here is the one below /* 70 */. There, we can see that the instruction produces two results of type MVT::i32 (the value produced by the instruction) respectively MVT::i16 (the CCReg updated by the instruction). These are labeled as results #10 respectively #11. Looking at operand identifiers after /*#Ops*/, we can see that only #10 is used by the rest of the resulting pattern (by INSERT_SUBREG), which is as intended. > > However, in the destination pattern declared in the *.td file, there is no information pertaining to which of the results should be used by the parent node. Since only tree-shaped patterns are allowed, SelectionIDAG must somehow decide which of the results are to be used by the parent node. And this decision is taken at lines 869-870 in DAGISelMatcherGen.cpp: > > ... > unsigned FinalNumOps = InstOps.size() + NumSubOps; > while (InstOps.size() < FinalNumOps) { > const TreePatternNode *Child = N->getChild(ChildNo); > unsigned BeforeAddingNumOps = InstOps.size(); > EmitResultOperand(Child, InstOps); > assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands"); > > // If the operand is an instruction and it produced multiple results, just > // take the first one. > if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction")) > InstOps.resize(BeforeAddingNumOps+1); > > ++ChildNo; > } > ... > > In other words, if a child produces more than one result SelectionIDAG always takes the first result. Those two lines originate from a patch by Chris Lattner (r99725), so presumably this is the correct way of doing it. If GlobalISel were to do the same, it would solve the issue I'm having with our patterns.Thanks for looking into that. There's three questions I feel I have with the SelectionDAG behaviour: * If Defs=[A] causes SelectionDAG to add a result to the intermediate SDNode, why doesn't Defs=[A,B] add two? * Given that SDNode's support MVT::Other results, why doesn't MVT::Other behave the same way? * If nothing can use that result, why model it? I suppose custom C++ instruction selection can still see it so maybe that's it but if so, what code is relying on it? The inconsistency makes me rather suspicious about it. It feels like it was a hack for a specific purpose but I don't know what that purpose is. Overall, I'm not keen to carry it forwards unless there's a clear reason it's there. Leaving that aside for the moment. I see a difference in modelling that makes directly importing the SelectionDAG behaviour tricky. SelectionDAG uses SDNode's which keep the result list (+ the first implicit def with known type) and the operand list separate. GlobalISel uses the MachineInstr's which uses a single list in a fixed order. That order is outputs, inputs, implicits so we would need to split the results list into two pieces and defer adding the implicit def to the place it's currently added to handle it the SelectionDAG way. That being the case (and assuming we don't find a good reason for SelectionDAG's behaviour), I think the best approach for this might be to adjust the numbers that originate from GetNumNodeResults() for the `InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other` case to undo the adjustment CodeGenDAGPatterns does. That's an ugly solution but I think the other ones I can think of are worse.> Best regards, > Gabriel > > From: Daniel Sanders <daniel_l_sanders at apple.com> > Sent: Friday, June 5, 2020 9:02 PM > To: Quentin Colombet <qcolombet at apple.com> > Cc: Dominik Montada <dominik.montada at hightec-rt.com>; Gabriel Hjort Åkerlund <gabriel.hjort.akerlund at ericsson.com>; llvm-dev at lists.llvm.org <llvm-dev at lists.llvm.org> > Subject: Re: [llvm-dev] Nested instruction patterns rejected by GlobalISel when having registers in Defs > > The implicit defs don't participate much in the patterns. For the most part it's just read into CodeGenInstruction::ImplicitDefs and then GlobalISel gathers and adds them all at the end. I think I do see the code Gabriel is referring to though. > GetNumNodeResults() has: > if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) > ++NumDefsToAdd; > and ultimately this VT gets into Types via UpdateNodeType(). I have no idea why this code does this as I don't really see why the VT matters to how you treat an implicit def. This code dates back to 2010 (r99726) and that commit called it 'funky logic' so it's unlikely that we'll find someone that remembers it. > > Does your CCReg need to have a specific type? If not, then you could make it MVT::Other and the problem should go away. > > Have you looked into how DAGISel supports these patterns? This code is common between DAGISel and GlobalISel so given that DAGISel works it must be doing something to handle this that's missing from GlobalISel. > > > On 5 Jun 2020, at 11:02, Quentin Colombet <qcolombet at apple.com <mailto:qcolombet at apple.com>> wrote: > > + Daniel who knows the most about the table gen importer > > > On Jun 5, 2020, at 12:48 AM, Dominik Montada via llvm-dev <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>> wrote: > > Hi Gabriel, > Your comment made me take a look at our instruction definitions and patterns in a little bit more detail. And while we do use nested patterns with INSERT_SUBREG, apparently none of those patterns use instructions with implicit-defs. Sorry for misleading you there by a wrong assumption on my part. > However, I still find it strange that TableGen should reject such a pattern. I'm really not sure if this is simply an overlooked use-case or if there is some real reasoning behind this logic. If it were an actual output register I could understand it, but since this is an implicit one it should not impact the pattern in my opinion. > Sorry for not being able to help out with the actual problem after all! > Cheers, > Dominik > Am 04.06.20 um 15:06 schrieb Gabriel Hjort Åkerlund: > Hi Dominik, > > Thanks for your reply. > > In my case, the Defs is the cause of the problem. Or rather, it is part of the problem, because when I remove it from the instruction TableGen gives me a different error message which concerns a part which is deeper into the pattern tree, so at least it is able to proceed beyond that part of the pattern. I have also stepped TableGen inside gdb and verified that having Defs causes GlobalISel to include CCReg in the Types field of the TreePatternNode corresponding to the instruction, which is what GlobalISel looks at to subsequently reject the pattern on basis that the instruction produces multiple results. > > But from your comment, I take it that the Defs field should never be considered actual output, is that correct? If so, I find it strange that CodeGenDAGPatterns, which parses the patterns, takes the CCReg into consideration as additional results. I am tempted to modify that part of the code, but maybe I’m missing some invariant that’s not immediately evident… > > Cheers, > Gabriel > > From: Dominik Montada <dominik.montada at hightec-rt.com> <mailto:dominik.montada at hightec-rt.com> > Sent: den 4 juni 2020 14:51 > To: llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org> > Cc: Gabriel Hjort Åkerlund <gabriel.hjort.akerlund at ericsson.com> <mailto:gabriel.hjort.akerlund at ericsson.com> > Subject: Re: [llvm-dev] Nested instruction patterns rejected by GlobalISel when having registers in Defs > > Hi Gabriel, > I'm working on a downstream target which uses GlobalISel and we have many patterns with instructions that also define a system register as a side-effect and use them without any problem. Since CCReg is not an actual output of the instruction, but an implicit definition, GlobalISel should have no trouble with it, so I'm guessing your problem lies somewhere. Have you tried running the tablegen command manually and looked at the output there? > The command is llvm-tblgen -gen-global-isel <couple of -I flags> <your_target>.td --write-if-changed --warn-on-skipped-patterns > I can't tell you exactly what -I flags you'll need but if you run ninja in verbose mode or look at the ninja build log, you should be able to see what is being used. > Word of caution however: sometimes TableGen gives you a very clear error message indicating what is wrong, sometimes it gives you a very cryptic error message. And sometimes it doesn't even give you that and behave as if everything is a-ok while it still hasn't included your pattern. I have lost countless hours trying to debug TableGen patterns with GlobalISel and there's still a lot of stuff that GlobalISel unfortunately does not support yet in TableGen. So be prepared to write some C++ code for the unsupported cases for the moment. > Cheers, > Dominik > Am 04.06.20 um 14:34 schrieb Gabriel Hjort Åkerlund via llvm-dev: > Hi, > > I am in the process of porting our target to GlobalISel, and have encountered a problem. Nearly all instructions in our instruction set make modifications to a CC register, and hence are defined as follows: > > let ..., Defs = [CCReg] in > def shfts_a32_imm7: Instruction<(outs OurRC:$dst), ...>; > > What’s more, many of these instructions have patterns where the instruction itself appears inside a nested tree, e.g.: > > def Pat<(source pattern ...), > (sext_a32 (INSERT_SUBREG (...), (shfts_a32_imm7 OurRC:$src, Imm7:$imm), ...>; > > Now to the problem: When TableGen processes the instruction above, it includes the CCReg in the Defs field along with the registers appearing in outs, thereby indicating that shfts_a32_imm7 produces two results. Currently, the GlobalISel-backend in TableGen requires that nested instructions appearing in the output pattern produce exactly one result. Consequently, TableGen rejects many of our patterns. But in reality, the instruction really only produces a single result and therefore this pattern should be allowed. > > So I wonder, how should registers appear in Defs be treated? Are they equal to those appearing in outs, and therefore interchangeable, or is it valid to disambiguate between them and therefore modify TableGen to only consider outs as the result of interest when processing the patterns? > > Gabriel Hjort Åkerlund > > > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org> > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev <https://protect2.fireeye.com/v1/url?k=52e18446-0c413e28-52e1c4dd-86b1886cfa64-f424e731a80348bd&q=1&e=238953c8-f0ec-4510-8c97-620bfb03d5be&u=https%3A%2F%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-dev> > -- > ---------------------------------------------------------------------- > Dominik Montada Email: dominik.montada at hightec-rt.com <mailto:dominik.montada at hightec-rt.com> > HighTec EDV-Systeme GmbH Phone: +49 681 92613 19 > Europaallee 19 Fax: +49-681-92613-26 > D-66113 Saarbrücken WWW: http://www.hightec-rt.com <https://protect2.fireeye.com/v1/url?k=a0228059-fe823a37-a022c0c2-86b1886cfa64-48b7aa6978940111&q=1&e=238953c8-f0ec-4510-8c97-620bfb03d5be&u=http%3A%2F%2Fwww.hightec-rt.com%2F> > > Managing Director: Vera Strothmann > Register Court: Saarbrücken, HRB 10445, VAT ID: DE 138344222 > > This e-mail may contain confidential and/or privileged information. If > you are not the intended recipient please notify the sender immediately > and destroy this e-mail. Any unauthorised copying, disclosure or > distribution of the material in this e-mail is strictly forbidden. > --- > -- > ---------------------------------------------------------------------- > Dominik Montada Email: dominik.montada at hightec-rt.com <mailto:dominik.montada at hightec-rt.com> > HighTec EDV-Systeme GmbH Phone: +49 681 92613 19 > Europaallee 19 Fax: +49-681-92613-26 > D-66113 Saarbrücken WWW: http://www.hightec-rt.com <https://protect2.fireeye.com/v1/url?k=b7cd53d5-e96de9bb-b7cd134e-861d41abace8-5636b949d44c6f9b&q=1&e=9aff5cfa-72fd-4986-af7c-78b27f9ea1e8&u=http%3A%2F%2Fwww.hightec-rt.com%2F> > > Managing Director: Vera Strothmann > Register Court: Saarbrücken, HRB 10445, VAT ID: DE 138344222 > > This e-mail may contain confidential and/or privileged information. If > you are not the intended recipient please notify the sender immediately > and destroy this e-mail. Any unauthorised copying, disclosure or > distribution of the material in this e-mail is strictly forbidden. > --- > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org> > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev <https://protect2.fireeye.com/v1/url?k=b3d033f0-ed70899e-b3d0736b-861d41abace8-91f0c9908116c6fb&q=1&e=9aff5cfa-72fd-4986-af7c-78b27f9ea1e8&u=https%3A%2F%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-dev>-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200609/59d62324/attachment-0001.html>
Gabriel Hjort Åkerlund via llvm-dev
2020-Jun-10 09:54 UTC
[llvm-dev] Nested instruction patterns rejected by GlobalISel when having registers in Defs
From: Daniel Sanders <daniel_l_sanders at apple.com>
Sent: den 9 juni 2020 20:21
To: Gabriel Hjort Åkerlund <gabriel.hjort.akerlund at ericsson.com>
Cc: Quentin Colombet <qcolombet at apple.com>; Dominik Montada
<dominik.montada at hightec-rt.com>; llvm-dev at lists.llvm.org
Subject: Re: [llvm-dev] Nested instruction patterns rejected by GlobalISel when
having registers in Defs
On 8 Jun 2020, at 08:13, Gabriel Hjort Åkerlund <gabriel.hjort.akerlund at
ericsson.com <mailto:gabriel.hjort.akerlund at ericsson.com> > wrote:
Hi Daniel,
Thanks for replying; I was hoping to get in touch with you on this issue.
I had a look at how SelectionIDAG does it when generating the matcher table, and
it does consider the implicit defs as additional output. Here is the match table
generated for the pattern:
/* 0*/ OPC_CheckOpcode, TARGET_VAL(ISD::SIGN_EXTEND),
/* 3*/ OPC_MoveChild0,
/* 4*/ OPC_CheckOpcode, TARGET_VAL(ISD::SHL),
/* 7*/ OPC_MoveChild0,
/* 8*/ OPC_CheckOpcode, TARGET_VAL(ISD::ANY_EXTEND),
/* 11*/ OPC_RecordChild0, // #0 = $src
/* 12*/ OPC_CheckChild0Type, MVT::i16,
/* 14*/ OPC_MoveParent,
/* 15*/ OPC_RecordChild1, // #1 = $imm
/* 16*/ OPC_MoveChild1,
/* 17*/ OPC_CheckOpcode, TARGET_VAL(ISD::Constant),
/* 20*/ OPC_CheckPredicate, 0, // Predicate_Imm_17_31_i16
/* 22*/ OPC_CheckType, MVT::i16,
/* 24*/ OPC_MoveParent,
/* 25*/ OPC_CheckType, MVT::i32,
/* 27*/ OPC_MoveParent,
/* 28*/ OPC_CheckType, MVT::i40,
/* 30*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::IMPLICIT_DEF), 0,
MVT::i40, 0/*#Ops*/, // Results = #2
/* 36*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::IMPLICIT_DEF), 0,
MVT::i32, 0/*#Ops*/, // Results = #3
/* 42*/ OPC_EmitInteger, MVT::i32, OurTarget::hi16, // Results = #4
/* 45*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::INSERT_SUBREG), 0,
MVT::i32, 3/*#Ops*/, 3, 0, 4, // Results = #5
/* 54*/ OPC_EmitNode1, TARGET_VAL(OurTarget::clearLo32_pseudo), 0,
MVT::i32, 1/*#Ops*/, 5, // Results = #6
/* 61*/ OPC_EmitInteger, MVT::i16, 0,
/* 64*/ OPC_EmitRegister, MVT::i16, 0 /*zero_reg*/,
/* 67*/ OPC_EmitInteger, MVT::i16, 0,
/* 70*/ OPC_EmitNode2, TARGET_VAL(OurTarget::shfts_a32_imm7), 0,
MVT::i32, MVT::i16, 5/*#Ops*/, 6, 1, 7, 8, 9, // Results = #10
#11
/* 82*/ OPC_EmitInteger, MVT::i32, OurTarget::acc,
/* 85*/ OPC_EmitNode1, TARGET_VAL(TargetOpcode::INSERT_SUBREG), 0,
MVT::i40, 3/*#Ops*/, 2, 10, 12, // Results = #13
/* 94*/ OPC_EmitInteger, MVT::i16, 0,
/* 97*/ OPC_EmitRegister, MVT::i16, 0 /*zero_reg*/,
/* 100*/ OPC_EmitInteger, MVT::i16, 0,
/* 103*/ OPC_MorphNodeTo1, TARGET_VAL(OurTarget::sext_a32), 0,
MVT::i40, 4/*#Ops*/, 13, 14, 15, 16, ...
The line of interest here is the one below /* 70 */. There, we can see that
the instruction produces two results of type MVT::i32 (the value produced by the
instruction) respectively MVT::i16 (the CCReg updated by the instruction). These
are labeled as results #10 respectively #11. Looking at operand identifiers
after /*#Ops*/, we can see that only #10 is used by the rest of the resulting
pattern (by INSERT_SUBREG), which is as intended.
However, in the destination pattern declared in the *.td file, there is no
information pertaining to which of the results should be used by the parent
node. Since only tree-shaped patterns are allowed, SelectionIDAG must somehow
decide which of the results are to be used by the parent node. And this decision
is taken at lines 869-870 in DAGISelMatcherGen.cpp:
...
unsigned FinalNumOps = InstOps.size() + NumSubOps;
while (InstOps.size() < FinalNumOps) {
const TreePatternNode *Child = N->getChild(ChildNo);
unsigned BeforeAddingNumOps = InstOps.size();
EmitResultOperand(Child, InstOps);
assert(InstOps.size() > BeforeAddingNumOps && "Didn't
add any operands");
// If the operand is an instruction and it produced multiple results, just
// take the first one.
if (!Child->isLeaf() &&
Child->getOperator()->isSubClassOf("Instruction"))
InstOps.resize(BeforeAddingNumOps+1);
++ChildNo;
}
...
In other words, if a child produces more than one result SelectionIDAG always
takes the first result. Those two lines originate from a patch by Chris Lattner
(r99725), so presumably this is the correct way of doing it. If GlobalISel were
to do the same, it would solve the issue I'm having with our patterns.
Thanks for looking into that.
There's three questions I feel I have with the SelectionDAG behaviour:
* If Defs=[A] causes SelectionDAG to add a result to the intermediate SDNode,
why doesn't Defs=[A,B] add two?
That’s because CodeGenDAGPatterns::GetNumNodeResults() does the following:
if (Operator->isSubClassOf("Instruction")) {
CodeGenInstruction &InstInfo =
CDP.getTargetInfo().getInstruction(Operator);
unsigned NumDefsToAdd = InstInfo.Operands.NumDefs;
// Subtract any defaulted outputs.
for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) {
Record *OperandNode = InstInfo.Operands[i].Rec;
if (OperandNode->isSubClassOf("OperandWithDefaultOps")
&&
!CDP.getDefaultOperand(OperandNode).DefaultOps.empty())
--NumDefsToAdd;
}
// Add on one implicit def if it has a resolvable type.
if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other)
++NumDefsToAdd;
return NumDefsToAdd;
}
In other words, when building the patterns any additional Defs are simply
ignored, and I think this is due to how the functionality evolved. Here are the
commits related to this issue:
commit f144725ebcd859009c6ee96ead4a2d09ab3d277c
Author: Chris Lattner <sabre at nondot.org>
Date: Fri Mar 19 21:37:09 2010 +0000
major surgery on tblgen: generalize TreePatternNode
to maintain a list of types (one for each result of
the node) instead of a single type. There are liberal
hacks added to emulate the old behavior in various
situations, but they can start disolving now.
llvm-svn: 98999
commit d44966f26de2e7ca05cb888a1ea5b5bdc22a65c0
Author: Chris Lattner <sabre at nondot.org>
Date: Sat Mar 27 19:15:02 2010 +0000
continue pushing tblgen's support for nodes with multiple
results forward. We can now handle an instruction that
produces one implicit def and one result instead of one or
the other when not at the root of the pattern.
llvm-svn: 99725
commit 7bc5d9b576827b4c629e7dd6707804ee61ef18c9
Author: Chris Lattner <sabre at nondot.org>
Date: Sat Mar 27 20:09:24 2010 +0000
hoist some funky logic into CodeGenInstruction
from two places in CodeGenDAGPatterns.cpp, and
use it in DAGISelMatcherGen.cpp instead of using
an incorrect predicate that happened to get lucky
on our current targets.
llvm-svn: 99726
commit 3a8eb896c9d6696402bf113653c4c20b237c7009
Author: Craig Topper <craig.topper at gmail.com>
Date: Fri Mar 20 05:09:06 2015 +0000
[Tablegen] Attempt to add support for patterns containing nodes with
multiple results.
This is needed for AVX512 masked scatter/gather support.
The R600 change is necessary to remove a hack that was working around the
lack of multiple results.
llvm-svn: 232798
My guess is that the support for multiple results simply stopped at one result
from outs and one from Defs.
* Given that SDNode's support MVT::Other results, why doesn't MVT::Other
behave the same way?
Hm, cannot answer that; I don’t know what SDNode’s support for MVT::Other looks
like.
* If nothing can use that result, why model it? I suppose custom C++ instruction
selection can still see it so maybe that's it but if so, what code is
relying on it?
Perhaps the commit above from Crag Topper can answer that. I haven’t looked
deeper into that, though.
The inconsistency makes me rather suspicious about it. It feels like it was a
hack for a specific purpose but I don't know what that purpose is. Overall,
I'm not keen to carry it forwards unless there's a clear reason it's
there.
Leaving that aside for the moment. I see a difference in modelling that makes
directly importing the SelectionDAG behaviour tricky. SelectionDAG uses
SDNode's which keep the result list (+ the first implicit def with known
type) and the operand list separate. GlobalISel uses the MachineInstr's
which uses a single list in a fixed order. That order is outputs, inputs,
implicits so we would need to split the results list into two pieces and defer
adding the implicit def to the place it's currently added to handle it the
SelectionDAG way. That being the case (and assuming we don't find a good
reason for SelectionDAG's behaviour), I think the best approach for this
might be to adjust the numbers that originate from GetNumNodeResults() for the
`InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other` case
to undo the adjustment CodeGenDAGPatterns does. That's an ugly solution but
I think the other ones I can think of are worse.
I am probably missing something here, but why does GlobalISel need to care about
implicit defs at all? Since there seems to be no way of referring to such values
in the patterns, why not just ignore them from instruction selection’s point of
view? As far as I know, only the register allocator needs to know about which
registers are implicitly used or defined by an instruction.
Best regards,
Gabriel
_____
From: Daniel Sanders <daniel_l_sanders at apple.com
<mailto:daniel_l_sanders at apple.com> >
Sent: Friday, June 5, 2020 9:02 PM
To: Quentin Colombet <qcolombet at apple.com <mailto:qcolombet at
apple.com> >
Cc: Dominik Montada <dominik.montada at hightec-rt.com
<mailto:dominik.montada at hightec-rt.com> >; Gabriel Hjort Åkerlund
<gabriel.hjort.akerlund at ericsson.com <mailto:gabriel.hjort.akerlund at
ericsson.com> >; llvm-dev at lists.llvm.org <mailto:llvm-dev at
lists.llvm.org> <llvm-dev at lists.llvm.org <mailto:llvm-dev at
lists.llvm.org> >
Subject: Re: [llvm-dev] Nested instruction patterns rejected by GlobalISel when
having registers in Defs
The implicit defs don't participate much in the patterns. For the most part
it's just read into CodeGenInstruction::ImplicitDefs and then GlobalISel
gathers and adds them all at the end. I think I do see the code Gabriel is
referring to though.
GetNumNodeResults() has:
if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other)
++NumDefsToAdd;
and ultimately this VT gets into Types via UpdateNodeType(). I have no idea why
this code does this as I don't really see why the VT matters to how you
treat an implicit def. This code dates back to 2010 (r99726) and that commit
called it 'funky logic' so it's unlikely that we'll find someone
that remembers it.
Does your CCReg need to have a specific type? If not, then you could make it
MVT::Other and the problem should go away.
Have you looked into how DAGISel supports these patterns? This code is common
between DAGISel and GlobalISel so given that DAGISel works it must be doing
something to handle this that's missing from GlobalISel.
On 5 Jun 2020, at 11:02, Quentin Colombet < <mailto:qcolombet at
apple.com> qcolombet at apple.com> wrote:
+ Daniel who knows the most about the table gen importer
On Jun 5, 2020, at 12:48 AM, Dominik Montada via llvm-dev <
<mailto:llvm-dev at lists.llvm.org> llvm-dev at lists.llvm.org> wrote:
Hi Gabriel,
Your comment made me take a look at our instruction definitions and patterns in
a little bit more detail. And while we do use nested patterns with
INSERT_SUBREG, apparently none of those patterns use instructions with
implicit-defs. Sorry for misleading you there by a wrong assumption on my part.
However, I still find it strange that TableGen should reject such a pattern.
I'm really not sure if this is simply an overlooked use-case or if there is
some real reasoning behind this logic. If it were an actual output register I
could understand it, but since this is an implicit one it should not impact the
pattern in my opinion.
Sorry for not being able to help out with the actual problem after all!
Cheers,
Dominik
Am 04.06.20 um 15:06 schrieb Gabriel Hjort Åkerlund:
Hi Dominik,
Thanks for your reply.
In my case, the Defs is the cause of the problem. Or rather, it is part of the
problem, because when I remove it from the instruction TableGen gives me a
different error message which concerns a part which is deeper into the pattern
tree, so at least it is able to proceed beyond that part of the pattern. I have
also stepped TableGen inside gdb and verified that having Defs causes GlobalISel
to include CCReg in the Types field of the TreePatternNode corresponding to the
instruction, which is what GlobalISel looks at to subsequently reject the
pattern on basis that the instruction produces multiple results.
But from your comment, I take it that the Defs field should never be considered
actual output, is that correct? If so, I find it strange that
CodeGenDAGPatterns, which parses the patterns, takes the CCReg into
consideration as additional results. I am tempted to modify that part of the
code, but maybe I’m missing some invariant that’s not immediately evident…
Cheers,
Gabriel
From: Dominik Montada <mailto:dominik.montada at hightec-rt.com>
<dominik.montada at hightec-rt.com>
Sent: den 4 juni 2020 14:51
To: <mailto:llvm-dev at lists.llvm.org> llvm-dev at lists.llvm.org
Cc: Gabriel Hjort Åkerlund <mailto:gabriel.hjort.akerlund at
ericsson.com> <gabriel.hjort.akerlund at ericsson.com>
Subject: Re: [llvm-dev] Nested instruction patterns rejected by GlobalISel when
having registers in Defs
Hi Gabriel,
I'm working on a downstream target which uses GlobalISel and we have many
patterns with instructions that also define a system register as a side-effect
and use them without any problem. Since CCReg is not an actual output of the
instruction, but an implicit definition, GlobalISel should have no trouble with
it, so I'm guessing your problem lies somewhere. Have you tried running the
tablegen command manually and looked at the output there?
The command is llvm-tblgen -gen-global-isel <couple of -I flags>
<your_target>.td --write-if-changed --warn-on-skipped-patterns
I can't tell you exactly what -I flags you'll need but if you run ninja
in verbose mode or look at the ninja build log, you should be able to see what
is being used.
Word of caution however: sometimes TableGen gives you a very clear error message
indicating what is wrong, sometimes it gives you a very cryptic error message.
And sometimes it doesn't even give you that and behave as if everything is
a-ok while it still hasn't included your pattern. I have lost countless
hours trying to debug TableGen patterns with GlobalISel and there's still a
lot of stuff that GlobalISel unfortunately does not support yet in TableGen. So
be prepared to write some C++ code for the unsupported cases for the moment.
Cheers,
Dominik
Am 04.06.20 um 14:34 schrieb Gabriel Hjort Åkerlund via llvm-dev:
Hi,
I am in the process of porting our target to GlobalISel, and have encountered a
problem. Nearly all instructions in our instruction set make modifications to a
CC register, and hence are defined as follows:
let ..., Defs = [CCReg] in
def shfts_a32_imm7: Instruction<(outs OurRC:$dst), ...>;
What’s more, many of these instructions have patterns where the instruction
itself appears inside a nested tree, e.g.:
def Pat<(source pattern ...),
(sext_a32 (INSERT_SUBREG (...), (shfts_a32_imm7 OurRC:$src, Imm7:$imm),
...>;
Now to the problem: When TableGen processes the instruction above, it includes
the CCReg in the Defs field along with the registers appearing in outs, thereby
indicating that shfts_a32_imm7 produces two results. Currently, the
GlobalISel-backend in TableGen requires that nested instructions appearing in
the output pattern produce exactly one result. Consequently, TableGen rejects
many of our patterns. But in reality, the instruction really only produces a
single result and therefore this pattern should be allowed.
So I wonder, how should registers appear in Defs be treated? Are they equal to
those appearing in outs, and therefore interchangeable, or is it valid to
disambiguate between them and therefore modify TableGen to only consider outs as
the result of interest when processing the patterns?
Gabriel Hjort Åkerlund
_______________________________________________
LLVM Developers mailing list
<mailto:llvm-dev at lists.llvm.org> llvm-dev at lists.llvm.org
<https://protect2.fireeye.com/v1/url?k=52e18446-0c413e28-52e1c4dd-86b1886cfa64-f424e731a80348bd&q=1&e=238953c8-f0ec-4510-8c97-620bfb03d5be&u=https%3A%2F%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-dev>
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
--
----------------------------------------------------------------------
Dominik Montada Email: <mailto:dominik.montada at
hightec-rt.com> dominik.montada at hightec-rt.com
HighTec EDV-Systeme GmbH Phone: +49 681 92613 19
Europaallee 19 Fax: +49-681-92613-26
D-66113 Saarbrücken WWW:
<https://protect2.fireeye.com/v1/url?k=a0228059-fe823a37-a022c0c2-86b1886cfa64-48b7aa6978940111&q=1&e=238953c8-f0ec-4510-8c97-620bfb03d5be&u=http%3A%2F%2Fwww.hightec-rt.com%2F>
http://www.hightec-rt.com
Managing Director: Vera Strothmann
Register Court: Saarbrücken, HRB 10445, VAT ID: DE 138344222
This e-mail may contain confidential and/or privileged information. If
you are not the intended recipient please notify the sender immediately
and destroy this e-mail. Any unauthorised copying, disclosure or
distribution of the material in this e-mail is strictly forbidden.
---
--
----------------------------------------------------------------------
Dominik Montada Email: <mailto:dominik.montada at
hightec-rt.com> dominik.montada at hightec-rt.com
HighTec EDV-Systeme GmbH Phone: +49 681 92613 19
Europaallee 19 Fax: +49-681-92613-26
D-66113 Saarbrücken WWW:
<https://protect2.fireeye.com/v1/url?k=b7cd53d5-e96de9bb-b7cd134e-861d41abace8-5636b949d44c6f9b&q=1&e=9aff5cfa-72fd-4986-af7c-78b27f9ea1e8&u=http%3A%2F%2Fwww.hightec-rt.com%2F>
http://www.hightec-rt.com
Managing Director: Vera Strothmann
Register Court: Saarbrücken, HRB 10445, VAT ID: DE 138344222
This e-mail may contain confidential and/or privileged information. If
you are not the intended recipient please notify the sender immediately
and destroy this e-mail. Any unauthorised copying, disclosure or
distribution of the material in this e-mail is strictly forbidden.
---
_______________________________________________
LLVM Developers mailing list
<mailto:llvm-dev at lists.llvm.org> llvm-dev at lists.llvm.org
<https://protect2.fireeye.com/v1/url?k=b3d033f0-ed70899e-b3d0736b-861d41abace8-91f0c9908116c6fb&q=1&e=9aff5cfa-72fd-4986-af7c-78b27f9ea1e8&u=https%3A%2F%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-dev>
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20200610/311dd8ed/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 6320 bytes
Desc: not available
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20200610/311dd8ed/attachment-0001.bin>
Maybe Matching Threads
- Nested instruction patterns rejected by GlobalISel when having registers in Defs
- Nested instruction patterns rejected by GlobalISel when having registers in Defs
- GlobalISel round table follow up: register bank select
- Correct modelling of instructions with types smaller than the register class
- Exceptions not getting caught on bare-metal target