[llvm] c3ee525 - [TableGen][GlobalISel] Support EXTRACT_SUBREGs for ComplexPattern suboperands.

Ivan Kosarev via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 27 04:10:30 PDT 2023


Author: Ivan Kosarev
Date: 2023-03-27T12:10:13+01:00
New Revision: c3ee525e0295e8dbea70613e409b6a6ff14981f0

URL: https://github.com/llvm/llvm-project/commit/c3ee525e0295e8dbea70613e409b6a6ff14981f0
DIFF: https://github.com/llvm/llvm-project/commit/c3ee525e0295e8dbea70613e409b6a6ff14981f0.diff

LOG: [TableGen][GlobalISel] Support EXTRACT_SUBREGs for ComplexPattern suboperands.

This makes it possible to write GlobalISel patterns generating
EXTRACT_SUBREG instructions applied to suboperands of ComplexPattern
operands. Currently, TableGen complains that such operands are not
declared in matcher.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D146800

Added: 
    

Modified: 
    llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
    llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
    llvm/test/TableGen/GlobalISelEmitterSubreg.td
    llvm/utils/TableGen/GlobalISelEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
index 7e9a601f7221f..8954d5cdcc377 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
@@ -349,16 +349,24 @@ enum {
   /// - InsnID - Instruction ID to modify
   /// - Imm - The immediate to add
   GIR_AddImm,
+
   /// Render complex operands to the specified instruction
   /// - InsnID - Instruction ID to modify
   /// - RendererID - The renderer to call
   GIR_ComplexRenderer,
-
   /// Render sub-operands of complex operands to the specified instruction
   /// - InsnID - Instruction ID to modify
   /// - RendererID - The renderer to call
   /// - RenderOpID - The suboperand to render.
   GIR_ComplexSubOperandRenderer,
+  /// Render subregisters of suboperands of complex operands to the
+  /// specified instruction
+  /// - InsnID - Instruction ID to modify
+  /// - RendererID - The renderer to call
+  /// - RenderOpID - The suboperand to render
+  /// - SubRegIdx - The subregister to extract
+  GIR_ComplexSubOperandSubRegRenderer,
+
   /// Render operands to the specified instruction using a custom function
   /// - InsnID - Instruction ID to modify
   /// - OldInsnID - Instruction ID to get the matched operand from

diff  --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
index 1db2fa2b34cb3..d2a03f119156c 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
@@ -1029,6 +1029,22 @@ bool InstructionSelector::executeMatchTable(
                              << RenderOpID << ")\n");
       break;
     }
+    case GIR_ComplexSubOperandSubRegRenderer: {
+      int64_t InsnID = MatchTable[CurrentIdx++];
+      int64_t RendererID = MatchTable[CurrentIdx++];
+      int64_t RenderOpID = MatchTable[CurrentIdx++];
+      int64_t SubRegIdx = MatchTable[CurrentIdx++];
+      MachineInstrBuilder &MI = OutMIs[InsnID];
+      assert(MI && "Attempted to add to undefined instruction");
+      State.Renderers[RendererID][RenderOpID](MI);
+      MI->getOperand(MI->getNumOperands() - 1).setSubReg(SubRegIdx);
+      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+                      dbgs() << CurrentIdx
+                             << ": GIR_ComplexSubOperandSubRegRenderer(OutMIs["
+                             << InsnID << "], " << RendererID << ", "
+                             << RenderOpID << ", " << SubRegIdx << ")\n");
+      break;
+    }
 
     case GIR_CopyConstantAsSImm: {
       int64_t NewInsnID = MatchTable[CurrentIdx++];

diff  --git a/llvm/test/TableGen/GlobalISelEmitterSubreg.td b/llvm/test/TableGen/GlobalISelEmitterSubreg.td
index 2865cbc700380..c8405735aaea0 100644
--- a/llvm/test/TableGen/GlobalISelEmitterSubreg.td
+++ b/llvm/test/TableGen/GlobalISelEmitterSubreg.td
@@ -33,6 +33,7 @@ def ERegs : MyClass<32, [i32], (sequence "E%u", 0, 0)>;
 def SOP : RegisterOperand<SRegs>;
 def DOP : RegisterOperand<DRegs>;
 def SOME_INSN : I<(outs DRegs:$dst), (ins DOP:$src), []>;
+def SOME_INSN2 : I<(outs DRegs:$dst), (ins DOP:$src1, DOP:$src2), []>;
 def SUBSOME_INSN : I<(outs SRegs:$dst), (ins SOP:$src), []>;
 def SUBSOME_INSN2 : I<(outs SRegs:$dst), (ins SOP:$src), []>;
 
@@ -41,6 +42,10 @@ def SUBSOME_INSN2 : I<(outs SRegs:$dst), (ins SOP:$src), []>;
 let isAllocatable = 0 in
 def SuperDRegs : MyClass<32, [i32], (add DRegs, ERegs)>;
 
+def complex : Operand<i32>, ComplexPattern<i32, 2, "SelectComplexOperand", []>;
+def gi_complex : GIComplexOperandMatcher<s32, "selectComplexOperand">,
+                 GIComplexPatternEquiv<complex>;
+
 // We should skip cases where we don't have a given register class for the
 // subregister source.
 // SKIPPED: def : Pat<(i32 (anyext i16:$src)), (INSERT_SUBREG (i32 (IMPLICIT_DEF)), i16:$src, sub0)>;
@@ -48,6 +53,31 @@ def SuperDRegs : MyClass<32, [i32], (add DRegs, ERegs)>;
 def : Pat<(i32 (anyext i16:$src)), (INSERT_SUBREG (i32 (IMPLICIT_DEF)), i16:$src, sub0)>;
 def : Pat<(i32 (anyext i16:$src)), (SOME_INSN (INSERT_SUBREG (i32 (IMPLICIT_DEF)), i16:$src, sub0))>;
 
+// Test EXTRACT_SUBREG applied to suboperands of a ComplexPattern
+// operand.
+def : Pat<(sub (complex DOP:$src1, DOP:$src2), 77),
+          (SOME_INSN2 (EXTRACT_SUBREG DOP:$src1, sub0),
+                      (EXTRACT_SUBREG DOP:$src2, sub1))>;
+// CHECK-LABEL: // (sub:{ *:[i32] } (complex:{ *:[i32] } DOP:{ *:[i32] }:$src1, DOP:{ *:[i32] }:$src2), 77:{ *:[i32] })  =>  (SOME_INSN2:{ *:[i32] } (EXTRACT_SUBREG:{ *:[i32] } DOP:{ *:[i32] }:$src1, sub0:{ *:[i32] }), (EXTRACT_SUBREG:{ *:[i32] } DOP:{ *:[i32] }:$src2, sub1:{ *:[i32] }))
+// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32,
+// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/1, /*TypeID*/GILLT_s32,
+// CHECK-NEXT: GIR_BuildMI, /*InsnID*/2, /*Opcode*/TargetOpcode::COPY,
+// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/2, /*TempRegID*/1, /*TempRegFlags*/RegState::Define,
+// CHECK-NEXT: GIR_ComplexSubOperandSubRegRenderer, /*InsnID*/2, /*RendererID*/0, /*SubOperand*/1, /*SubRegIdx*/2, // src2
+// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/2, /*Op*/0, Test::SRegsRegClassID,
+// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/2, /*Op*/1, Test::DRegsRegClassID,
+// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::COPY,
+// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/RegState::Define,
+// CHECK-NEXT: GIR_ComplexSubOperandSubRegRenderer, /*InsnID*/1, /*RendererID*/0, /*SubOperand*/0, /*SubRegIdx*/1, // src1
+// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/0, Test::SRegsRegClassID,
+// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/1, Test::DRegsRegClassID,
+// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::SOME_INSN2,
+// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0,
+// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/1, /*TempRegFlags*/0,
+// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+
 // Test that we import INSERT_SUBREG when its subregister source has a given
 // class.
 def : Pat<(i32 (anyext i16:$src)), (INSERT_SUBREG (i32 (IMPLICIT_DEF)), SOP:$src, sub0)>;

diff  --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index 666253ac43b3d..592dd38582abb 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -3002,6 +3002,8 @@ class RenderComplexPatternOperand : public OperandRenderer {
   /// When provided, this is the suboperand of the ComplexPattern operand to
   /// render. Otherwise all the suboperands will be rendered.
   std::optional<unsigned> SubOperand;
+  /// The subregister to extract. Render the whole register if not specified.
+  const CodeGenSubRegIndex *SubReg;
 
   unsigned getNumOperands() const {
     return TheDef.getValueAsDag("Operands")->getNumArgs();
@@ -3010,24 +3012,30 @@ class RenderComplexPatternOperand : public OperandRenderer {
 public:
   RenderComplexPatternOperand(unsigned InsnID, const Record &TheDef,
                               StringRef SymbolicName, unsigned RendererID,
-                              std::optional<unsigned> SubOperand = std::nullopt)
+                              std::optional<unsigned> SubOperand = std::nullopt,
+                              const CodeGenSubRegIndex *SubReg = nullptr)
       : OperandRenderer(OR_ComplexPattern), InsnID(InsnID), TheDef(TheDef),
         SymbolicName(SymbolicName), RendererID(RendererID),
-        SubOperand(SubOperand) {}
+        SubOperand(SubOperand), SubReg(SubReg) {}
 
   static bool classof(const OperandRenderer *R) {
     return R->getKind() == OR_ComplexPattern;
   }
 
   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
-    Table << MatchTable::Opcode(SubOperand ? "GIR_ComplexSubOperandRenderer"
-                                           : "GIR_ComplexRenderer")
+    Table << MatchTable::Opcode(
+                 SubOperand ? (SubReg ? "GIR_ComplexSubOperandSubRegRenderer"
+                                      : "GIR_ComplexSubOperandRenderer")
+                            : "GIR_ComplexRenderer")
           << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID)
           << MatchTable::Comment("RendererID")
           << MatchTable::IntValue(RendererID);
     if (SubOperand)
       Table << MatchTable::Comment("SubOperand")
             << MatchTable::IntValue(*SubOperand);
+    if (SubReg)
+      Table << MatchTable::Comment("SubRegIdx")
+            << MatchTable::IntValue(SubReg->EnumValue);
     Table << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
   }
 };
@@ -4914,8 +4922,15 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
         return failedImport("EXTRACT_SUBREG requires an additional COPY");
     }
 
-    DstMIBuilder.addRenderer<CopySubRegRenderer>(Dst->getChild(0)->getName(),
-                                                 SubIdx);
+    StringRef RegOperandName = Dst->getChild(0)->getName();
+    if (const auto &SubOperand = M.getComplexSubOperand(RegOperandName)) {
+      DstMIBuilder.addRenderer<RenderComplexPatternOperand>(
+          *std::get<0>(*SubOperand), RegOperandName, std::get<1>(*SubOperand),
+          std::get<2>(*SubOperand), SubIdx);
+      return InsertPt;
+    }
+
+    DstMIBuilder.addRenderer<CopySubRegRenderer>(RegOperandName, SubIdx);
     return InsertPt;
   }
 


        


More information about the llvm-commits mailing list