[llvm] r306388 - [globalisel][tablegen] Add support for EXTRACT_SUBREG.

Daniel Sanders via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 27 09:44:38 PDT 2017


No worries :-). Thanks for fixing it.

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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170627/c98d350d/attachment.html>


More information about the llvm-commits mailing list