From 7fb62030d995455f6182db30337b8786a5184f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Hjort=20=C3=85kerlund?= Date: Fri, 18 Sep 2020 10:08:32 +0200 Subject: [PATCH] [TableGen][GlobalISel] Fix handling of zero_reg When generating matching tables for GlobalISel, TableGen would output "::zero_reg" whenever encountering the zero_reg, which in turn would result in compilation error. This patch fixes that by instead outputting NoRegister (== 0), which is the same result that TableGen produces when generating matching tables for ISelDAG. Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D86215 --- lib/Target/ARM/ARMInstructionSelector.cpp | 2 - test/TableGen/GlobalISelEmitter-zero-reg.td | 42 +++++++++++++++++++++ utils/TableGen/CodeGenTarget.cpp | 5 +++ utils/TableGen/CodeGenTarget.h | 3 ++ utils/TableGen/GlobalISelEmitter.cpp | 32 +++++++++------- 5 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 test/TableGen/GlobalISelEmitter-zero-reg.td diff --git a/lib/Target/ARM/ARMInstructionSelector.cpp b/lib/Target/ARM/ARMInstructionSelector.cpp index c8a894fb11a..09a94cc3a8e 100644 --- a/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/lib/Target/ARM/ARMInstructionSelector.cpp @@ -164,8 +164,6 @@ createARMInstructionSelector(const ARMBaseTargetMachine &TM, } } -const unsigned zero_reg = 0; - #define GET_GLOBALISEL_IMPL #include "ARMGenGlobalISel.inc" #undef GET_GLOBALISEL_IMPL diff --git a/test/TableGen/GlobalISelEmitter-zero-reg.td b/test/TableGen/GlobalISelEmitter-zero-reg.td new file mode 100644 index 00000000000..374430bc427 --- /dev/null +++ b/test/TableGen/GlobalISelEmitter-zero-reg.td @@ -0,0 +1,42 @@ +// RUN: llvm-tblgen -gen-global-isel -optimize-match-table=false -I %p/../../include -I %p/Common %s -o - < %s | FileCheck %s + +include "llvm/Target/Target.td" +include "GlobalISelEmitterCommon.td" + +def P0 : Register<"p0"> { let Namespace = "MyTarget"; } +def PR32 : RegisterClass<"MyTarget", [i32], 32, (add P0)>; +def PR32Op : RegisterOperand; + +def pred : PredicateOperand {} +class PredI Pat> + : Instruction { + let Namespace = "MyTarget"; + let OutOperandList = OOps; + let InOperandList = !con(IOps, (ins pred:$pred)); + let Pattern = Pat; +} + +def INST : PredI<(outs GPR32:$dst), (ins GPR32:$src), []>; + +// CHECK: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2, +// CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_LOAD, +// CHECK-NEXT: GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0, +// CHECK-NEXT: GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(int64_t)AtomicOrdering::NotAtomic, +// CHECK-NEXT: // MIs[0] dst +// CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32, +// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID, +// CHECK-NEXT: // MIs[0] src +// CHECK-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32, +// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID, +// CHECK-NEXT: // (ld:{ *:[i32] } GPR32:{ *:[i32] }:$src)<><> => (INST:{ *:[i32] } GPR32:{ *:[i32] }:$src) +// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INST, +// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst +// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src +// CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::NoRegister, /*AddRegisterRegFlags*/0, +// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*MergeInsnID's*/0, GIU_MergeMemOperands_EndOfList, +// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, +// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0, +def : Pat<(i32 (load GPR32:$src)), + (INST GPR32:$src)>; diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 889110a2dc2..302d3e9098d 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -266,6 +266,11 @@ StringRef CodeGenTarget::getInstNamespace() const { return ""; } +StringRef CodeGenTarget::getRegNamespace() const { + auto &RegClasses = RegBank->getRegClasses(); + return RegClasses.size() > 0 ? RegClasses.front().Namespace : ""; +} + Record *CodeGenTarget::getInstructionSet() const { return TargetRec->getValueAsDef("InstructionSet"); } diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 6c89f34c50e..44bc46a0a42 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -73,6 +73,9 @@ public: /// StringRef getInstNamespace() const; + /// getRegNamespace - Return the target-specific register namespace. + StringRef getRegNamespace() const; + /// getInstructionSet - Return the InstructionSet object. /// Record *getInstructionSet() const; diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp index 67b68217cbd..752ca109d1c 100644 --- a/utils/TableGen/GlobalISelEmitter.cpp +++ b/utils/TableGen/GlobalISelEmitter.cpp @@ -2729,12 +2729,13 @@ protected: unsigned InsnID; const Record *RegisterDef; bool IsDef; + const CodeGenTarget &Target; public: - AddRegisterRenderer(unsigned InsnID, const Record *RegisterDef, - bool IsDef = false) + AddRegisterRenderer(unsigned InsnID, const CodeGenTarget &Target, + const Record *RegisterDef, bool IsDef = false) : OperandRenderer(OR_Register), InsnID(InsnID), RegisterDef(RegisterDef), - IsDef(IsDef) {} + IsDef(IsDef), Target(Target) {} static bool classof(const OperandRenderer *R) { return R->getKind() == OR_Register; @@ -2742,13 +2743,17 @@ public: void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override { Table << MatchTable::Opcode("GIR_AddRegister") - << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID) - << MatchTable::NamedValue( - (RegisterDef->getValue("Namespace") - ? RegisterDef->getValueAsString("Namespace") - : ""), - RegisterDef->getName()) - << MatchTable::Comment("AddRegisterRegFlags"); + << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID); + if (RegisterDef->getName() != "zero_reg") { + Table << MatchTable::NamedValue( + (RegisterDef->getValue("Namespace") + ? RegisterDef->getValueAsString("Namespace") + : ""), + RegisterDef->getName()); + } else { + Table << MatchTable::NamedValue(Target.getRegNamespace(), "NoRegister"); + } + Table << MatchTable::Comment("AddRegisterRegFlags"); // TODO: This is encoded as a 64-bit element, but only 16 or 32-bits are // really needed for a physical register reference. We can pack the @@ -4419,7 +4424,7 @@ Expected GlobalISelEmitter::importExplicitUseRenderer( return failedImport("Dst operand has an unsupported type"); if (ChildRec->isSubClassOf("Register")) { - DstMIBuilder.addRenderer(ChildRec); + DstMIBuilder.addRenderer(Target, ChildRec); return InsertPt; } @@ -4479,7 +4484,8 @@ Expected GlobalISelEmitter::createAndImportInstructionRenderer( &Target.getInstruction(RK.getDef("COPY"))); BuildMIAction &CopyToPhysRegMIBuilder = *static_cast(InsertPt->get()); - CopyToPhysRegMIBuilder.addRenderer(PhysInput.first, + CopyToPhysRegMIBuilder.addRenderer(Target, + PhysInput.first, true); CopyToPhysRegMIBuilder.addRenderer(PhysInput.first); } @@ -4870,7 +4876,7 @@ Error GlobalISelEmitter::importDefaultOperandRenderers( IDMIBuilder.addRenderer(TempRegID); DstMIBuilder.addRenderer(TempRegID); } else { - DstMIBuilder.addRenderer(Def); + DstMIBuilder.addRenderer(Target, Def); } continue; }