Skip to content

Commit 53f6715

Browse files
committed
[GlobalISel] Support physical register inputs in nested patterns
When importing nested patterns, we create InsnMatcher for each pattern and miss them if consider only the top level InsnMatcher. Iterate all InsnMatchers of PhysRegOperands when generating COPYs for physical registers.
1 parent 815343e commit 53f6715

File tree

3 files changed

+60
-12
lines changed

3 files changed

+60
-12
lines changed

llvm/test/TableGen/GlobalISelEmitter/gisel-physreg-input.td

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,45 @@ class I<dag OOps, dag IOps, list<dag> Pat>
2222
let Pattern = Pat;
2323
}
2424

25+
// Try a nested physical register
26+
27+
// GISEL: GIM_Try,
28+
// GISEL-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
29+
// GISEL-NEXT: GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_STORE),
30+
// GISEL-NEXT: GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(uint8_t)AtomicOrdering::NotAtomic,
31+
// GISEL-NEXT: // MIs[0] src0
32+
// GISEL-NEXT: GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s32,
33+
// GISEL-NEXT: GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPR32RegClassID),
34+
// GISEL-NEXT: // MIs[0] Operand 1
35+
// GISEL-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
36+
// GISEL-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
37+
// GISEL-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/3,
38+
// GISEL-NEXT: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_MUL),
39+
// GISEL-NEXT: // MIs[1] Operand 0
40+
// GISEL-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
41+
// GISEL-NEXT: // MIs[1] src1
42+
// GISEL-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
43+
// GISEL-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR32RegClassID),
44+
// GISEL-NEXT: // MIs[1] Operand 2
45+
// GISEL-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
46+
// GISEL-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/GIMT_Encode2(MyTarget::Special32RegClassID),
47+
// GISEL-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/1,
48+
// GISEL-NEXT: // (st GPR32:{ *:[i32] }:$src0, (mul:{ *:[i32] } GPR32:{ *:[i32] }:$src1, SPECIAL:{ *:[i32] })) => (MULM_PHYS GPR32:{ *:[i32] }:$src0, GPR32:{ *:[i32] }:$src1)
49+
// GISEL-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY),
50+
// GISEL-NEXT: GIR_AddRegister, /*InsnID*/1, GIMT_Encode2(MyTarget::SPECIAL), /*AddRegisterRegFlags*/GIMT_Encode2(RegState::Define),
51+
// GISEL-NEXT: GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/1, /*OpIdx*/2, // SPECIAL
52+
// GISEL-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::MULM_PHYS),
53+
// GISEL-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // src0
54+
// GISEL-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
55+
// GISEL-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*NumInsns*/2, /*MergeInsnID's*/0, 1,
56+
// GISEL-NEXT: GIR_RootConstrainSelectedInstOperands,
57+
// GISEL-NEXT: // GIR_Coverage, 0,
58+
// GISEL-NEXT: GIR_EraseRootFromParent_Done,
59+
def MULM_PHYS : I<(outs), (ins GPR32:$src0, GPR32:$src1),
60+
[(st GPR32:$src0, (mul GPR32:$src1, SPECIAL))]> {
61+
let Uses = [SPECIAL];
62+
}
63+
2564
// Try a normal physical register use.
2665

2766
// GISEL: GIM_Try,
@@ -44,7 +83,7 @@ class I<dag OOps, dag IOps, list<dag> Pat>
4483
// GISEL-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
4584
// GISEL-NEXT: GIR_RootToRootCopy, /*OpIdx*/1, // src0
4685
// GISEL-NEXT: GIR_RootConstrainSelectedInstOperands,
47-
// GISEL-NEXT: // GIR_Coverage, 0,
86+
// GISEL-NEXT: // GIR_Coverage, 1,
4887
// GISEL-NEXT: GIR_EraseRootFromParent_Done,
4988
def ADD_PHYS : I<(outs GPR32:$dst), (ins GPR32:$src0),
5089
[(set GPR32:$dst, (add GPR32:$src0, SPECIAL))]> {
@@ -73,7 +112,7 @@ def ADD_PHYS : I<(outs GPR32:$dst), (ins GPR32:$src0),
73112
// GISEL-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
74113
// GISEL-NEXT: GIR_RootToRootCopy, /*OpIdx*/1, // SPECIAL
75114
// GISEL-NEXT: GIR_RootConstrainSelectedInstOperands,
76-
// GISEL-NEXT: // GIR_Coverage, 1,
115+
// GISEL-NEXT: // GIR_Coverage, 2,
77116
// GISEL-NEXT: GIR_EraseRootFromParent_Done,
78117
def MUL_PHYS : I<(outs GPR32:$dst), (ins GPR32:$SPECIAL),
79118
[(set GPR32:$dst, (mul GPR32:$SPECIAL, SPECIAL))]> {

llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,11 @@ class RuleMatcher : public Matcher {
492492
/// the renderers.
493493
StringMap<OperandMatcher *> DefinedOperands;
494494

495+
using PhysRegOperandsTy = DenseMap<const Record *, OperandMatcher *>;
496+
495497
/// A map of anonymous physical register operands defined by the matchers that
496498
/// may be referenced by the renderers.
497-
DenseMap<const Record *, OperandMatcher *> PhysRegOperands;
499+
PhysRegOperandsTy PhysRegOperands;
498500

499501
/// ID for the next instruction variable defined with
500502
/// implicitlyDefineInsnVar()
@@ -695,6 +697,10 @@ class RuleMatcher : public Matcher {
695697
unsigned allocateOutputInsnID() { return NextOutputInsnID++; }
696698
unsigned allocateTempRegID() { return NextTempRegID++; }
697699

700+
iterator_range<PhysRegOperandsTy::const_iterator> physoperands() const {
701+
return make_range(PhysRegOperands.begin(), PhysRegOperands.end());
702+
}
703+
698704
iterator_range<MatchersTy::iterator> insnmatchers() {
699705
return make_range(Matchers.begin(), Matchers.end());
700706
}

llvm/utils/TableGen/GlobalISelEmitter.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,15 +1412,18 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
14121412
action_iterator InsertPt = InsertPtOrError.get();
14131413
BuildMIAction &DstMIBuilder = *static_cast<BuildMIAction *>(InsertPt->get());
14141414

1415-
for (auto PhysInput : InsnMatcher.getPhysRegInputs()) {
1416-
InsertPt = M.insertAction<BuildMIAction>(
1417-
InsertPt, M.allocateOutputInsnID(),
1418-
&Target.getInstruction(RK.getDef("COPY")));
1419-
BuildMIAction &CopyToPhysRegMIBuilder =
1420-
*static_cast<BuildMIAction *>(InsertPt->get());
1421-
CopyToPhysRegMIBuilder.addRenderer<AddRegisterRenderer>(
1422-
Target, PhysInput.first, true);
1423-
CopyToPhysRegMIBuilder.addRenderer<CopyPhysRegRenderer>(PhysInput.first);
1415+
for (auto PhysOp : M.physoperands()) {
1416+
auto &OpInsnMatcher = PhysOp.second->getInstructionMatcher();
1417+
for (auto PhysInput : OpInsnMatcher.getPhysRegInputs()) {
1418+
InsertPt = M.insertAction<BuildMIAction>(
1419+
InsertPt, M.allocateOutputInsnID(),
1420+
&Target.getInstruction(RK.getDef("COPY")));
1421+
BuildMIAction &CopyToPhysRegMIBuilder =
1422+
*static_cast<BuildMIAction *>(InsertPt->get());
1423+
CopyToPhysRegMIBuilder.addRenderer<AddRegisterRenderer>(
1424+
Target, PhysInput.first, true);
1425+
CopyToPhysRegMIBuilder.addRenderer<CopyPhysRegRenderer>(PhysInput.first);
1426+
}
14241427
}
14251428

14261429
if (auto Error = importExplicitDefRenderers(InsertPt, M, DstMIBuilder, Dst,

0 commit comments

Comments
 (0)