From: Ivan Kosarev Date: Mon, 27 Mar 2023 10:37:16 +0000 (+0100) Subject: [TableGen][GlobalISel] Support EXTRACT_SUBREGs for ComplexPattern suboperands. X-Git-Tag: upstream/17.0.6~13601 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c3ee525e0295e8dbea70613e409b6a6ff14981f0;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h index 7e9a601..8954d5c 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 1db2fa2..d2a03f1 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 2865cbc..c840573 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; def DOP : RegisterOperand; 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, ComplexPattern; +def gi_complex : GIComplexOperandMatcher, + GIComplexPatternEquiv; + // 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 666253a..592dd38 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -3002,6 +3002,8 @@ private: /// When provided, this is the suboperand of the ComplexPattern operand to /// render. Otherwise all the suboperands will be rendered. std::optional 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 @@ private: public: RenderComplexPatternOperand(unsigned InsnID, const Record &TheDef, StringRef SymbolicName, unsigned RendererID, - std::optional SubOperand = std::nullopt) + std::optional 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 GlobalISelEmitter::importExplicitUseRenderers( return failedImport("EXTRACT_SUBREG requires an additional COPY"); } - DstMIBuilder.addRenderer(Dst->getChild(0)->getName(), - SubIdx); + StringRef RegOperandName = Dst->getChild(0)->getName(); + if (const auto &SubOperand = M.getComplexSubOperand(RegOperandName)) { + DstMIBuilder.addRenderer( + *std::get<0>(*SubOperand), RegOperandName, std::get<1>(*SubOperand), + std::get<2>(*SubOperand), SubIdx); + return InsertPt; + } + + DstMIBuilder.addRenderer(RegOperandName, SubIdx); return InsertPt; }