<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"><!-- P {margin-top:0;margin-bottom:0;} --></style>
</head>
<body dir="ltr">
<div id="divtagdefaultwrapper" style="font-size:11pt;color:#000000;font-family:Calibri,Helvetica,sans-serif;" dir="ltr">
<div id="divtagdefaultwrapper" style="font-size: 11pt; color: rgb(0, 0, 0); font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols;" dir="ltr">
<p>Hello,</p>
<p><br>
</p>
<p>We appear to have a windows-debug build error from what I think is this commit, a crash in tblgen:</p>
<p><br>
</p>
<p></p>
<div> 0x00007FF9E6CA0806 (0x00007FF735189138 0x00007FF735188DE0 0x000000F300000A52 0xCCCCCCCCCCCCCCCC), ?_Debug_message@std@@YAXPEB_W0I@Z() + 0x46 bytes(s)</div>
<div> 0x00007FF7345F58E1 (0x000000F3A0A6CA50 0x000000F3A0A6C898 0x000000F3A5BB8570 0x00007FF735188DE0), std::_Debug_lt_pred<<lambda_83a80e87367d92ad251c7c618cd76f21> & __ptr64,std::pair<llvm::CodeGenRegisterClass * __ptr64,llvm::BitVector> &
__ptr64,std::pair<llvm::CodeGenRegisterClass * __ptr64,llvm::BitVector> & __ptr64>() + 0x81 bytes(s), c:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility, line 896 + 0x54 byte(s)</div>
<div> 0x00007FF734608251 (0x000000F3A5BB8550 0x000000F3A5BB85F0 0x000000F3A0A6CA50 0xCCCCCCCCCCCCCCCC), std::_Insertion_sort_unchecked<std::pair<llvm::CodeGenRegisterClass * __ptr64,llvm::BitVector> * __ptr64,<lambda_83a80e87367d92ad251c7c618cd76f21>
>() + 0x151 bytes(s), c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm, line 2642 + 0x34 byte(s)</div>
<div> 0x00007FF734611B78 (0x000000F3A5BB8550 0x000000F3A5BB85F0 0x0000000000000005 0x000000F3A0A6CA50), std::_Sort_unchecked1<std::pair<llvm::CodeGenRegisterClass * __ptr64,llvm::BitVector> * __ptr64,__int64,<lambda_83a80e87367d92ad251c7c618cd76f21>
>() + 0x198 bytes(s), c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm, line 2770</div>
<div> 0x00007FF734611E13 (0x000000F3A5BB8550 0x000000F3A5BB85F0 0x000000F3A0A6CA50 0xCCCCCCCC00000ADF), std::_Sort_unchecked<std::pair<llvm::CodeGenRegisterClass * __ptr64,llvm::BitVector> * __ptr64,<lambda_83a80e87367d92ad251c7c618cd76f21>
>() + 0x53 bytes(s), c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm, line 2777</div>
<div> 0x00007FF7346232E2 (0x000000F3A0A6CDF8 0x000000F3A0A6CDD8 0x000000F3A0A6CA64 0xCCCCCCCCCCCCCCCC), std::sort<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<std::pair<llvm::CodeGenRegisterClass * __ptr64,llvm::BitVector> > > >,<lambda_83a80e87367d92ad251c7c618cd76f21>
>() + 0x102 bytes(s), c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm, line 2785</div>
<div> 0x00007FF7345DA928 (0x000000F3A8B9AAF0 0x000000F3A0A6CF58 0x000000F3A0A6E868 0x000000F3A5BB4150), llvm::CodeGenRegisterClass::getMatchingSubClassWithSubRegs() + 0x428 bytes(s), c:\work\trunk\work\src\llvm\utils\tablegen\codegenregisters.cpp,
line 964</div>
<div> 0x00007FF7348051B8 (0x000000F3A0A6E660 0x000000F3A0A6D848 0x000000F3A0A6D470 0x000000F3A989E3F0), `anonymous namespace'::GlobalISelEmitter::createAndImportInstructionRenderer() + 0x5F8 bytes(s), c:\work\trunk\work\src\llvm\utils\tablegen\globaliselemitter.cpp,
line 1674 + 0x2E byte(s)</div>
<div> 0x00007FF7348071CA (0x000000F3A0A6E660 0x000000F3A0A6DF40 0x000000F3A9BD09A0 0xCCCCCCCCCCCCCCCC), `anonymous namespace'::GlobalISelEmitter::runOnPattern() + 0xDEA bytes(s), c:\work\trunk\work\src\llvm\utils\tablegen\globaliselemitter.cpp,
line 1840</div>
<div> 0x00007FF734802866 (0x000000F3A0A6E660 0x000000F3A0A6F290 0xCCCCCCCCCCCCCCCC 0xCCCCCCCCCCCCCCCC), `anonymous namespace'::GlobalISelEmitter::run() + 0x1D6 bytes(s), c:\work\trunk\work\src\llvm\utils\tablegen\globaliselemitter.cpp, line
1934</div>
<div> 0x00007FF734807B2D (0x000000F3A0A6EFA8 0x000000F3A0A6F290 0xCCCCCCCCCCCCCCCC 0xCCCCCCCCCCCCCCCC), llvm::EmitGlobalISel() + 0x5D bytes(s), c:\work\trunk\work\src\llvm\utils\tablegen\globaliselemitter.cpp, line 2056 + 0x22 byte(s)</div>
<div> 0x00007FF73497AA39 (0x000000F3A0A6F290 0x000000F3A0A6EFA8 0x000000F3A0A6F228 0xCCCCCCCC00000004), `anonymous namespace'::LLVMTableGenMain() + 0x739 bytes(s), c:\work\trunk\work\src\llvm\utils\tablegen\tablegen.cpp, line 192</div>
<div> 0x00007FF734B2A155 (0x000000F3A0C9F210 0x00007FF73497A300 0x000000F3A0A6F670 0x0000000000000000), llvm::TableGenMain() + 0x605 bytes(s), c:\work\trunk\work\src\llvm\lib\tablegen\main.cpp, line 109 + 0x1C byte(s)</div>
<div> 0x00007FF73497ABFD (0x00007FF70000000B 0x000000F3A0C9F1B0 0x0000000000000000 0x00007FF73516ABD0), main() + 0x10D bytes(s), c:\work\trunk\work\src\llvm\utils\tablegen\tablegen.cpp, line 212 + 0x21 byte(s)</div>
<div> 0x00007FF734FC4584 (0x00007FF73516A000 0x00007FF73516A670 0x0000000000000000 0x0000000000000000), invoke_main() + 0x34 bytes(s), f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl, line 65</div>
<div> 0x00007FF734FC4447 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000), __scrt_common_main_seh() + 0x127 bytes(s), f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl, line 253 + 0x5 byte(s)</div>
<div> 0x00007FF734FC430E (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000), __scrt_common_main() + 0xE bytes(s), f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl, line 296</div>
<div> 0x00007FF734FC45A9 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000), mainCRTStartup() + 0x9 bytes(s), f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp, line 17</div>
<div> 0x00007FF9FC9D13D2 (0x00007FF9FC9D13B0 0x0000000000000000 0x0000000000000000 0x0000000000000000), BaseThreadInitThunk() + 0x22 bytes(s)</div>
<div> 0x00007FF9FCB254E4 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000), RtlUserThreadStart() + 0x34 bytes(s)</div>
<br>
<p></p>
Sorry if that is hard to read. It looks like it's complaining about the <span>SizeOrder lambda not being in strict weak ordering. Changing the "<span>return A->getMembers().size() >= B->getMembers().size();" to be a ">" seems to get it build.</span></span></div>
<div id="divtagdefaultwrapper" style="font-size: 11pt; color: rgb(0, 0, 0); font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols;" dir="ltr">
<span><span><br>
</span></span></div>
<div id="divtagdefaultwrapper" style="font-size: 11pt; color: rgb(0, 0, 0); font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols;" dir="ltr">
<span><span>Are you happy to make that a ">"?</span></span></div>
<div id="divtagdefaultwrapper" style="font-size: 11pt; color: rgb(0, 0, 0); font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols;" dir="ltr">
<span><span><br>
</span></span></div>
<div id="divtagdefaultwrapper" style="font-size: 11pt; color: rgb(0, 0, 0); font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols;" dir="ltr">
Cheers</div>
<div id="divtagdefaultwrapper" style="font-size: 11pt; color: rgb(0, 0, 0); font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols;" dir="ltr">
<span style="font-size: 11pt;">Dave</span><br>
</div>
<div id="divtagdefaultwrapper" style="font-size: 11pt; color: rgb(0, 0, 0); font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols;" dir="ltr">
<br>
<div style="color: rgb(0, 0, 0);">
<div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> llvm-commits <llvm-commits-bounces@lists.llvm.org> on behalf of Daniel Sanders via llvm-commits <llvm-commits@lists.llvm.org><br>
<b>Sent:</b> 27 June 2017 11:11<br>
<b>To:</b> llvm-commits@lists.llvm.org<br>
<b>Subject:</b> [llvm] r306388 - [globalisel][tablegen] Add support for EXTRACT_SUBREG.</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">Author: dsanders<br>
Date: Tue Jun 27 03:11:39 2017<br>
New Revision: 306388<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=306388&view=rev">http://llvm.org/viewvc/llvm-project?rev=306388&view=rev</a><br>
Log:<br>
[globalisel][tablegen] Add support for EXTRACT_SUBREG.<br>
<br>
Summary:<br>
After this patch, we finally have test cases that require multiple<br>
instruction emission.<br>
<br>
Depends on D33590<br>
<br>
Reviewers: ab, qcolombet, t.p.northover, rovka, kristof.beyls<br>
<br>
Subscribers: javed.absar, llvm-commits, igorb<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D33596">https://reviews.llvm.org/D33596</a><br>
<br>
Modified:<br>
llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp<br>
llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-trunc.mir<br>
llvm/trunk/utils/TableGen/CodeGenRegisters.cpp<br>
llvm/trunk/utils/TableGen/CodeGenRegisters.h<br>
llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp<br>
<br>
Modified: llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp?rev=306388&r1=306387&r2=306388&view=diff">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp?rev=306388&r1=306387&r2=306388&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp (original)<br>
+++ llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp Tue Jun 27 03:11:39 2017<br>
@@ -947,7 +947,7 @@ bool AArch64InstructionSelector::select(<br>
const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);<br>
<br>
if (DstRB.getID() != SrcRB.getID()) {<br>
- DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");<br>
+ DEBUG(dbgs() << "G_TRUNC/G_PTRTOINT input/output on different banks\n");<br>
return false;<br>
}<br>
<br>
@@ -964,16 +964,21 @@ bool AArch64InstructionSelector::select(<br>
<br>
if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||<br>
!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {<br>
- DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");<br>
+ DEBUG(dbgs() << "Failed to constrain G_TRUNC/G_PTRTOINT\n");<br>
return false;<br>
}<br>
<br>
if (DstRC == SrcRC) {<br>
// Nothing to be done<br>
+ } else if (Opcode == TargetOpcode::G_TRUNC && DstTy == LLT::scalar(32) &&<br>
+ SrcTy == LLT::scalar(64)) {<br>
+ llvm_unreachable("TableGen can import this case");<br>
+ return false;<br>
} else if (DstRC == &AArch64::GPR32RegClass &&<br>
SrcRC == &AArch64::GPR64RegClass) {<br>
I.getOperand(1).setSubReg(AArch64::sub_32);<br>
} else {<br>
+ DEBUG(dbgs() << "Unhandled mismatched classes in G_TRUNC/G_PTRTOINT\n");<br>
return false;<br>
}<br>
<br>
<br>
Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-trunc.mir<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-trunc.mir?rev=306388&r1=306387&r2=306388&view=diff">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-trunc.mir?rev=306388&r1=306387&r2=306388&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-trunc.mir (original)<br>
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-trunc.mir Tue Jun 27 03:11:39 2017<br>
@@ -15,8 +15,8 @@ legalized: true<br>
regBankSelected: true<br>
<br>
# CHECK: registers:<br>
-# CHECK-NEXT: - { id: 0, class: gpr64, preferred-register: '' }<br>
-# CHECK-NEXT: - { id: 1, class: gpr32, preferred-register: '' }<br>
+# CHECK-NEXT: - { id: 0, class: gpr64sp, preferred-register: '' }<br>
+# CHECK-NEXT: - { id: 1, class: gpr32sp, preferred-register: '' }<br>
registers:<br>
- { id: 0, class: gpr }<br>
- { id: 1, class: gpr }<br>
<br>
Modified: llvm/trunk/utils/TableGen/CodeGenRegisters.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenRegisters.cpp?rev=306388&r1=306387&r2=306388&view=diff">
http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenRegisters.cpp?rev=306388&r1=306387&r2=306388&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/utils/TableGen/CodeGenRegisters.cpp (original)<br>
+++ llvm/trunk/utils/TableGen/CodeGenRegisters.cpp Tue Jun 27 03:11:39 2017<br>
@@ -915,6 +915,84 @@ void CodeGenRegisterClass::computeSubCla<br>
RC.inheritProperties(RegBank);<br>
}<br>
<br>
+Optional<std::pair<CodeGenRegisterClass *, CodeGenRegisterClass *>><br>
+CodeGenRegisterClass::getMatchingSubClassWithSubRegs(<br>
+ CodeGenRegBank &RegBank, const CodeGenSubRegIndex *SubIdx) const {<br>
+ auto SizeOrder = [](const CodeGenRegisterClass *A,<br>
+ const CodeGenRegisterClass *B) {<br>
+ return A->getMembers().size() >= B->getMembers().size();<br>
+ };<br>
+<br>
+ auto &RegClasses = RegBank.getRegClasses();<br>
+<br>
+ // Find all the subclasses of this one that fully support the sub-register<br>
+ // index and order them by size. BiggestSuperRC should always be first.<br>
+ CodeGenRegisterClass *BiggestSuperRegRC = getSubClassWithSubReg(SubIdx);<br>
+ if (!BiggestSuperRegRC)<br>
+ return None;<br>
+ BitVector SuperRegRCsBV = BiggestSuperRegRC->getSubClasses();<br>
+ std::vector<CodeGenRegisterClass *> SuperRegRCs;<br>
+ for (auto &RC : RegClasses)<br>
+ if (SuperRegRCsBV[RC.EnumValue])<br>
+ SuperRegRCs.emplace_back(&RC);<br>
+ std::sort(SuperRegRCs.begin(), SuperRegRCs.end(), SizeOrder);<br>
+ assert(SuperRegRCs.front() == BiggestSuperRegRC && "Biggest class wasn't first");<br>
+<br>
+ // Find all the subreg classes and order them by size too.<br>
+ std::vector<std::pair<CodeGenRegisterClass *, BitVector>> SuperRegClasses;<br>
+ for (auto &RC: RegClasses) {<br>
+ BitVector SuperRegClassesBV(RegClasses.size());<br>
+ RC.getSuperRegClasses(SubIdx, SuperRegClassesBV);<br>
+ if (SuperRegClassesBV.any())<br>
+ SuperRegClasses.push_back(std::make_pair(&RC, SuperRegClassesBV));<br>
+ }<br>
+ std::sort(SuperRegClasses.begin(), SuperRegClasses.end(),<br>
+ [&](const std::pair<CodeGenRegisterClass *, BitVector> &A,<br>
+ const std::pair<CodeGenRegisterClass *, BitVector> &B) {<br>
+ return SizeOrder(A.first, B.first);<br>
+ });<br>
+<br>
+ // Find the biggest subclass and subreg class such that R:subidx is in the<br>
+ // subreg class for all R in subclass.<br>
+ //<br>
+ // For example:<br>
+ // All registers in X86's GR64 have a sub_32bit subregister but no class<br>
+ // exists that contains all the 32-bit subregisters because GR64 contains RIP<br>
+ // but GR32 does not contain EIP. Instead, we constrain SuperRegRC to<br>
+ // GR32_with_sub_8bit (which is identical to GR32_with_sub_32bit) and then,<br>
+ // having excluded RIP, we are able to find a SubRegRC (GR32).<br>
+ CodeGenRegisterClass *ChosenSuperRegClass = nullptr;<br>
+ CodeGenRegisterClass *SubRegRC = nullptr;<br>
+ for (auto *SuperRegRC : SuperRegRCs) {<br>
+ for (const auto &SuperRegClassPair : SuperRegClasses) {<br>
+ const BitVector &SuperRegClassBV = SuperRegClassPair.second;<br>
+ if (SuperRegClassBV[SuperRegRC->EnumValue]) {<br>
+ SubRegRC = SuperRegClassPair.first;<br>
+ ChosenSuperRegClass = SuperRegRC;<br>
+<br>
+ // If SubRegRC is bigger than SuperRegRC then there are members of<br>
+ // SubRegRC that don't have super registers via SubIdx. Keep looking to<br>
+ // find a better fit and fall back on this one if there isn't one.<br>
+ //<br>
+ // This is intended to prevent X86 from making odd choices such as<br>
+ // picking LOW32_ADDR_ACCESS_RBP instead of GR32 in the example above.<br>
+ // LOW32_ADDR_ACCESS_RBP is a valid choice but contains registers that<br>
+ // aren't subregisters of SuperRegRC whereas GR32 has a direct 1:1<br>
+ // mapping.<br>
+ if (SuperRegRC->getMembers().size() >= SubRegRC->getMembers().size())<br>
+ return std::make_pair(ChosenSuperRegClass, SubRegRC);<br>
+ }<br>
+ }<br>
+<br>
+ // If we found a fit but it wasn't quite ideal because SubRegRC had excess<br>
+ // registers, then we're done.<br>
+ if (ChosenSuperRegClass)<br>
+ return std::make_pair(ChosenSuperRegClass, SubRegRC);<br>
+ }<br>
+<br>
+ return None;<br>
+}<br>
+<br>
void CodeGenRegisterClass::getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,<br>
BitVector &Out) const {<br>
auto FindI = SuperRegClasses.find(SubIdx);<br>
<br>
Modified: llvm/trunk/utils/TableGen/CodeGenRegisters.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenRegisters.h?rev=306388&r1=306387&r2=306388&view=diff">
http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenRegisters.h?rev=306388&r1=306387&r2=306388&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/utils/TableGen/CodeGenRegisters.h (original)<br>
+++ llvm/trunk/utils/TableGen/CodeGenRegisters.h Tue Jun 27 03:11:39 2017<br>
@@ -329,6 +329,9 @@ namespace llvm {<br>
const std::string &getName() const { return Name; }<br>
std::string getQualifiedName() const;<br>
ArrayRef<MVT::SimpleValueType> getValueTypes() const {return VTs;}<br>
+ bool hasValueType(MVT::SimpleValueType VT) const {<br>
+ return std::find(VTs.begin(), VTs.end(), VT) != VTs.end();<br>
+ }<br>
unsigned getNumValueTypes() const { return VTs.size(); }<br>
<br>
MVT::SimpleValueType getValueTypeNum(unsigned VTNum) const {<br>
@@ -360,6 +363,18 @@ namespace llvm {<br>
return SubClassWithSubReg.lookup(SubIdx);<br>
}<br>
<br>
+ /// Find largest subclass where all registers have SubIdx subregisters in<br>
+ /// SubRegClass and the largest subregister class that contains those<br>
+ /// subregisters without (as far as possible) also containing additional registers.<br>
+ ///<br>
+ /// This can be used to find a suitable pair of classes for subregister copies.<br>
+ /// \return std::pair<SubClass, SubRegClass> where SubClass is a SubClass is<br>
+ /// a class where every register has SubIdx and SubRegClass is a class where<br>
+ /// every register is covered by the SubIdx subregister of SubClass.<br>
+ Optional<std::pair<CodeGenRegisterClass *, CodeGenRegisterClass *>><br>
+ getMatchingSubClassWithSubRegs(CodeGenRegBank &RegBank,<br>
+ const CodeGenSubRegIndex *SubIdx) const;<br>
+<br>
void setSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx,<br>
CodeGenRegisterClass *SubRC) {<br>
SubClassWithSubReg[SubIdx] = SubRC;<br>
@@ -370,7 +385,7 @@ namespace llvm {<br>
void getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,<br>
BitVector &Out) const;<br>
<br>
- // addSuperRegClass - Add a class containing only SudIdx super-registers.<br>
+ // addSuperRegClass - Add a class containing only SubIdx super-registers.<br>
void addSuperRegClass(CodeGenSubRegIndex *SubIdx,<br>
CodeGenRegisterClass *SuperRC) {<br>
SuperRegClasses[SubIdx].insert(SuperRC);<br>
<br>
Modified: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp?rev=306388&r1=306387&r2=306388&view=diff">
http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp?rev=306388&r1=306387&r2=306388&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp (original)<br>
+++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp Tue Jun 27 03:11:39 2017<br>
@@ -832,7 +832,13 @@ public:<br>
//===- Actions ------------------------------------------------------------===//<br>
class OperandRenderer {<br>
public:<br>
- enum RendererKind { OR_Copy, OR_Imm, OR_Register, OR_ComplexPattern };<br>
+ enum RendererKind {<br>
+ OR_Copy,<br>
+ OR_CopySubReg,<br>
+ OR_Imm,<br>
+ OR_Register,<br>
+ OR_ComplexPattern<br>
+ };<br>
<br>
protected:<br>
RendererKind Kind;<br>
@@ -877,6 +883,42 @@ public:<br>
}<br>
};<br>
<br>
+/// A CopySubRegRenderer emits code to copy a single register operand from an<br>
+/// existing instruction to the one being built and indicate that only a<br>
+/// subregister should be copied.<br>
+class CopySubRegRenderer : public OperandRenderer {<br>
+protected:<br>
+ /// The matcher for the instruction that this operand is copied from.<br>
+ /// This provides the facility for looking up an a operand by it's name so<br>
+ /// that it can be used as a source for the instruction being built.<br>
+ const InstructionMatcher &Matched;<br>
+ /// The name of the operand.<br>
+ const StringRef SymbolicName;<br>
+ /// The subregister to extract.<br>
+ const CodeGenSubRegIndex *SubReg;<br>
+<br>
+public:<br>
+ CopySubRegRenderer(const InstructionMatcher &Matched, StringRef SymbolicName,<br>
+ const CodeGenSubRegIndex *SubReg)<br>
+ : OperandRenderer(OR_CopySubReg), Matched(Matched),<br>
+ SymbolicName(SymbolicName), SubReg(SubReg) {}<br>
+<br>
+ static bool classof(const OperandRenderer *R) {<br>
+ return R->getKind() == OR_CopySubReg;<br>
+ }<br>
+<br>
+ const StringRef getSymbolicName() const { return SymbolicName; }<br>
+<br>
+ void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {<br>
+ const OperandMatcher &Operand = Matched.getOperand(SymbolicName);<br>
+ StringRef InsnVarName =<br>
+ Rule.getInsnVarName(Operand.getInstructionMatcher());<br>
+ std::string OperandExpr = Operand.getOperandExpr(InsnVarName);<br>
+ OS << " MIB.addReg(" << OperandExpr << ".getReg() /*" << SymbolicName<br>
+ << "*/, 0, " << SubReg->EnumValue << ");\n";<br>
+ }<br>
+};<br>
+<br>
/// Adds a specific physical register to the instruction being built.<br>
/// This is typically useful for WZR/XZR on AArch64.<br>
class AddRegisterRenderer : public OperandRenderer {<br>
@@ -1292,6 +1334,7 @@ private:<br>
const RecordKeeper &RK;<br>
const CodeGenDAGPatterns CGP;<br>
const CodeGenTarget &Target;<br>
+ CodeGenRegBank CGRegs;<br>
<br>
/// Keep track of the equivalence between SDNodes and Instruction.<br>
/// This is defined using 'GINodeEquiv' in the target description.<br>
@@ -1315,9 +1358,9 @@ private:<br>
Error importChildMatcher(InstructionMatcher &InsnMatcher,<br>
const TreePatternNode *SrcChild, unsigned OpIdx,<br>
unsigned &TempOpIdx) const;<br>
- Expected<BuildMIAction &> createAndImportInstructionRenderer(<br>
- RuleMatcher &M, const TreePatternNode *Dst,<br>
- const InstructionMatcher &InsnMatcher) const;<br>
+ Expected<BuildMIAction &><br>
+ createAndImportInstructionRenderer(RuleMatcher &M, const TreePatternNode *Dst,<br>
+ const InstructionMatcher &InsnMatcher);<br>
Error importExplicitUseRenderer(BuildMIAction &DstMIBuilder,<br>
TreePatternNode *DstChild,<br>
const InstructionMatcher &InsnMatcher) const;<br>
@@ -1354,7 +1397,7 @@ const CodeGenInstruction *GlobalISelEmit<br>
}<br>
<br>
GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)<br>
- : RK(RK), CGP(RK), Target(CGP.getTargetInfo()) {}<br>
+ : RK(RK), CGP(RK), Target(CGP.getTargetInfo()), CGRegs(RK) {}<br>
<br>
//===- Emitter ------------------------------------------------------------===//<br>
<br>
@@ -1585,7 +1628,7 @@ Error GlobalISelEmitter::importExplicitU<br>
<br>
Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(<br>
RuleMatcher &M, const TreePatternNode *Dst,<br>
- const InstructionMatcher &InsnMatcher) const {<br>
+ const InstructionMatcher &InsnMatcher) {<br>
Record *DstOp = Dst->getOperator();<br>
if (!DstOp->isSubClassOf("Instruction")) {<br>
if (DstOp->isSubClassOf("ValueType"))<br>
@@ -1597,13 +1640,17 @@ Expected<BuildMIAction &> GlobalISelEmit<br>
<br>
unsigned DstINumUses = DstI->Operands.size() - DstI->Operands.NumDefs;<br>
unsigned ExpectedDstINumUses = Dst->getNumChildren();<br>
+ bool IsExtractSubReg = false;<br>
<br>
// COPY_TO_REGCLASS is just a copy with a ConstrainOperandToRegClassAction<br>
- // attached.<br>
+ // attached. Similarly for EXTRACT_SUBREG except that's a subregister copy.<br>
if (DstI->TheDef->getName() == "COPY_TO_REGCLASS") {<br>
DstI = &Target.getInstruction(RK.getDef("COPY"));<br>
DstINumUses--; // Ignore the class constraint.<br>
ExpectedDstINumUses--;<br>
+ } else if (DstI->TheDef->getName() == "EXTRACT_SUBREG") {<br>
+ DstI = &Target.getInstruction(RK.getDef("COPY"));<br>
+ IsExtractSubReg = true;<br>
}<br>
<br>
auto &DstMIBuilder = M.addAction<BuildMIAction>("NewI", DstI, InsnMatcher);<br>
@@ -1614,6 +1661,32 @@ Expected<BuildMIAction &> GlobalISelEmit<br>
DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstIOperand.Name);<br>
}<br>
<br>
+ // EXTRACT_SUBREG needs to use a subregister COPY.<br>
+ if (IsExtractSubReg) {<br>
+ if (!Dst->getChild(0)->isLeaf())<br>
+ return failedImport("EXTRACT_SUBREG child #1 is not a leaf");<br>
+<br>
+ if (DefInit *SubRegInit = dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue())) {<br>
+ CodeGenRegisterClass *RC = CGRegs.getRegClass(<br>
+ getInitValueAsRegClass(Dst->getChild(0)->getLeafValue()));<br>
+ CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());<br>
+<br>
+ const auto &SrcRCDstRCPair =<br>
+ RC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);<br>
+ if (SrcRCDstRCPair.hasValue()) {<br>
+ assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");<br>
+ if (SrcRCDstRCPair->first != RC)<br>
+ return failedImport("EXTRACT_SUBREG requires an additional COPY");<br>
+ }<br>
+<br>
+ DstMIBuilder.addRenderer<CopySubRegRenderer>(<br>
+ InsnMatcher, Dst->getChild(0)->getName(), SubIdx);<br>
+ return DstMIBuilder;<br>
+ }<br>
+<br>
+ return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");<br>
+ }<br>
+<br>
// Render the explicit uses.<br>
unsigned Child = 0;<br>
unsigned NumDefaultOps = 0;<br>
@@ -1740,6 +1813,16 @@ Expected<RuleMatcher> GlobalISelEmitter:<br>
if (DstIOpRec == nullptr)<br>
return failedImport(<br>
"COPY_TO_REGCLASS operand #1 isn't a register class");<br>
+ } else if (DstI.TheDef->getName() == "EXTRACT_SUBREG") {<br>
+ if (!Dst->getChild(0)->isLeaf())<br>
+ return failedImport("EXTRACT_SUBREG operand #0 isn't a leaf");<br>
+<br>
+ // We can assume that a subregister is in the same bank as it's super register.<br>
+ DstIOpRec = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());<br>
+<br>
+ if (DstIOpRec == nullptr)<br>
+ return failedImport(<br>
+ "EXTRACT_SUBREG operand #0 isn't a register class");<br>
} else if (DstIOpRec->isSubClassOf("RegisterOperand"))<br>
DstIOpRec = DstIOpRec->getValueAsDef("RegClass");<br>
else if (!DstIOpRec->isSubClassOf("RegisterClass"))<br>
@@ -1776,8 +1859,58 @@ Expected<RuleMatcher> GlobalISelEmitter:<br>
<br>
M.addAction<ConstrainOperandToRegClassAction>(<br>
"NewI", 0, Target.getRegisterClass(DstIOpRec));<br>
- } else<br>
- M.addAction<ConstrainOperandsToDefinitionAction>("NewI");<br>
+<br>
+ // We're done with this pattern! It's eligible for GISel emission; return<br>
+ // it.<br>
+ ++NumPatternImported;<br>
+ return std::move(M);<br>
+ }<br>
+<br>
+ if (DstI.TheDef->getName() == "EXTRACT_SUBREG") {<br>
+ // EXTRACT_SUBREG selects into a subregister COPY but unlike most<br>
+ // instructions, the result register class is controlled by the<br>
+ // subregisters of the operand. As a result, we must constrain the result<br>
+ // class rather than check that it's already the right one.<br>
+ if (!Dst->getChild(0)->isLeaf())<br>
+ return failedImport("EXTRACT_SUBREG child #1 is not a leaf");<br>
+<br>
+ if (DefInit *SubRegInit =<br>
+ dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue())) {<br>
+ // Constrain the result to the same register bank as the operand.<br>
+ Record *DstIOpRec =<br>
+ getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());<br>
+<br>
+ if (DstIOpRec == nullptr)<br>
+ return failedImport("EXTRACT_SUBREG operand #1 isn't a register class");<br>
+<br>
+ CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());<br>
+ CodeGenRegisterClass *SrcRC = CGRegs.getRegClass(<br>
+ getInitValueAsRegClass(Dst->getChild(0)->getLeafValue()));<br>
+<br>
+ // It would be nice to leave this constraint implicit but we're required<br>
+ // to pick a register class so constrain the result to a register class<br>
+ // that can hold the correct MVT.<br>
+ //<br>
+ // FIXME: This may introduce an extra copy if the chosen class doesn't<br>
+ // actually contain the subregisters.<br>
+ assert(Src->getExtTypes().size() == 1);<br>
+<br>
+ const auto &SrcRCDstRCPair =<br>
+ SrcRC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);<br>
+ assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");<br>
+ M.addAction<ConstrainOperandToRegClassAction>("NewI", 0, *SrcRCDstRCPair->second);<br>
+ M.addAction<ConstrainOperandToRegClassAction>("NewI", 1, *SrcRCDstRCPair->first);<br>
+<br>
+ // We're done with this pattern! It's eligible for GISel emission; return<br>
+ // it.<br>
+ ++NumPatternImported;<br>
+ return std::move(M);<br>
+ }<br>
+<br>
+ return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");<br>
+ }<br>
+<br>
+ M.addAction<ConstrainOperandsToDefinitionAction>("NewI");<br>
<br>
// We're done with this pattern! It's eligible for GISel emission; return it.<br>
++NumPatternImported;<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
llvm-commits@lists.llvm.org<br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</div>
</span></font></div>
</div>
</div>
</body>
</html>