[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