[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
This commit is contained in:
Gabriel Hjort Åkerlund 2020-09-18 10:08:32 +02:00 committed by Bjorn Pettersson
parent 2afe4becec
commit c10200536f
5 changed files with 69 additions and 15 deletions

View File

@ -164,8 +164,6 @@ createARMInstructionSelector(const ARMBaseTargetMachine &TM,
}
}
const unsigned zero_reg = 0;
#define GET_GLOBALISEL_IMPL
#include "ARMGenGlobalISel.inc"
#undef GET_GLOBALISEL_IMPL

View File

@ -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<PR32>;
def pred : PredicateOperand<OtherVT,
(ops PR32:$FR),
(ops (i32 zero_reg))> {}
class PredI<dag OOps, dag IOps, list<dag> 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)<<P:Predicate_unindexedload>><<P:Predicate_load>> => (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)>;

View File

@ -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");
}

View File

@ -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;

View File

@ -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<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
return failedImport("Dst operand has an unsupported type");
if (ChildRec->isSubClassOf("Register")) {
DstMIBuilder.addRenderer<AddRegisterRenderer>(ChildRec);
DstMIBuilder.addRenderer<AddRegisterRenderer>(Target, ChildRec);
return InsertPt;
}
@ -4479,7 +4484,8 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
&Target.getInstruction(RK.getDef("COPY")));
BuildMIAction &CopyToPhysRegMIBuilder =
*static_cast<BuildMIAction *>(InsertPt->get());
CopyToPhysRegMIBuilder.addRenderer<AddRegisterRenderer>(PhysInput.first,
CopyToPhysRegMIBuilder.addRenderer<AddRegisterRenderer>(Target,
PhysInput.first,
true);
CopyToPhysRegMIBuilder.addRenderer<CopyPhysRegRenderer>(PhysInput.first);
}
@ -4870,7 +4876,7 @@ Error GlobalISelEmitter::importDefaultOperandRenderers(
IDMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
} else {
DstMIBuilder.addRenderer<AddRegisterRenderer>(Def);
DstMIBuilder.addRenderer<AddRegisterRenderer>(Target, Def);
}
continue;
}