Skip to content

Commit cf4375d

Browse files
authored
[TableGen][GISel] Extract common function for determining MI's regclass (llvm#120135)
Add some comments that hopefully clarify a few things. This was supposed to be NFC, but there is a difference in the inferred register class for EXTRACT_SUBREG. Pull Request: llvm#120135
1 parent ce4ac99 commit cf4375d

File tree

2 files changed

+75
-77
lines changed

2 files changed

+75
-77
lines changed

llvm/test/TableGen/GlobalISelEmitter-nested-subregs.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def A0 : RegisterClass<"MyTarget", [i32], 32, (add a0)>;
3434
// CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_ANYEXT),
3535
// CHECK-NEXT: // MIs[0] DstI[dst]
3636
// CHECK-NEXT: GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s16,
37-
// CHECK-NEXT: GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::A0RegClassID),
37+
// CHECK-NEXT: GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::A0wRegClassID),
3838
// CHECK-NEXT: // MIs[0] src
3939
// CHECK-NEXT: GIM_RootCheckType, /*Op*/1, /*Type*/GILLT_s8,
4040
// CHECK-NEXT: // (anyext:{ *:[i16] } i8:{ *:[i8] }:$src) => (EXTRACT_SUBREG:{ *:[i16] } (INSERT_SUBREG:{ *:[i32] } (IMPLICIT_DEF:{ *:[i32] }), A0b:{ *:[i8] }:$src, lo8:{ *:[i32] }), lo16:{ *:[i32] })

llvm/utils/TableGen/GlobalISelEmitter.cpp

Lines changed: 74 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,10 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
459459
const CodeGenRegisterClass *
460460
inferRegClassFromPattern(const TreePatternNode &N);
461461

462+
const CodeGenRegisterClass *
463+
inferRegClassFromInstructionPattern(const TreePatternNode &N,
464+
unsigned ResIdx);
465+
462466
Error constrainOperands(action_iterator InsertPt, RuleMatcher &M,
463467
unsigned InsnID, const TreePatternNode &Dst);
464468

@@ -1856,46 +1860,85 @@ GlobalISelEmitter::inferRegClassFromPattern(const TreePatternNode &N) {
18561860

18571861
// Don't want to try and infer things when there could potentially be more
18581862
// than one candidate register class.
1859-
auto &Inst = Target.getInstruction(OpRec);
1863+
return inferRegClassFromInstructionPattern(N, /*ResIdx=*/0);
1864+
}
1865+
1866+
const CodeGenRegisterClass *
1867+
GlobalISelEmitter::inferRegClassFromInstructionPattern(const TreePatternNode &N,
1868+
unsigned ResIdx) {
1869+
const CodeGenInstruction &Inst = Target.getInstruction(N.getOperator());
1870+
assert(ResIdx < Inst.Operands.NumDefs &&
1871+
"Can only infer register class for explicit defs");
18601872

18611873
// Handle any special-case instructions which we can safely infer register
18621874
// classes from.
18631875
StringRef InstName = Inst.TheDef->getName();
1864-
bool IsRegSequence = InstName == "REG_SEQUENCE";
1865-
if (IsRegSequence || InstName == "COPY_TO_REGCLASS") {
1866-
// If we have a COPY_TO_REGCLASS, then we need to handle it specially. It
1867-
// has the desired register class as the first child.
1868-
const TreePatternNode &RCChild = N.getChild(IsRegSequence ? 0 : 1);
1876+
if (InstName == "REG_SEQUENCE") {
1877+
// (outs $super_dst), (ins $dst_regclass, variable_ops)
1878+
// Destination register class is explicitly specified by the first operand.
1879+
const TreePatternNode &RCChild = N.getChild(0);
18691880
if (!RCChild.isLeaf())
18701881
return nullptr;
18711882
return getRegClassFromLeaf(RCChild);
18721883
}
1884+
1885+
if (InstName == "COPY_TO_REGCLASS") {
1886+
// (outs $dst), (ins $src, $dst_regclass)
1887+
// Destination register class is explicitly specified by the second operand.
1888+
const TreePatternNode &RCChild = N.getChild(1);
1889+
if (!RCChild.isLeaf())
1890+
return nullptr;
1891+
return getRegClassFromLeaf(RCChild);
1892+
}
1893+
18731894
if (InstName == "INSERT_SUBREG") {
1895+
// (outs $super_dst), (ins $super_src, $sub_src, $sub_idx);
1896+
// If we can infer the register class for the first operand, use that.
1897+
// Otherwise, find a register class that supports both the specified
1898+
// sub-register index and the type of the instruction's result.
18741899
const TreePatternNode &Child0 = N.getChild(0);
18751900
assert(Child0.getNumTypes() == 1 && "Unexpected number of types!");
1876-
const TypeSetByHwMode &VTy = Child0.getExtType(0);
1877-
return inferSuperRegisterClassForNode(VTy, Child0, N.getChild(2));
1901+
return inferSuperRegisterClassForNode(N.getExtType(0), Child0,
1902+
N.getChild(2));
18781903
}
1904+
18791905
if (InstName == "EXTRACT_SUBREG") {
1880-
assert(N.getNumTypes() == 1 && "Unexpected number of types!");
1881-
const TypeSetByHwMode &VTy = N.getExtType(0);
1882-
return inferSuperRegisterClass(VTy, N.getChild(1));
1906+
// (outs $sub_dst), (ins $super_src, $sub_idx)
1907+
// Find a register class that can be used for a sub-register copy from
1908+
// the specified source at the specified sub-register index.
1909+
const CodeGenRegisterClass *SuperRC =
1910+
inferRegClassFromPattern(N.getChild(0));
1911+
if (!SuperRC)
1912+
return nullptr;
1913+
1914+
const CodeGenSubRegIndex *SubIdx = inferSubRegIndexForNode(N.getChild(1));
1915+
if (!SubIdx)
1916+
return nullptr;
1917+
1918+
const auto SubRCAndSubRegRC =
1919+
SuperRC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);
1920+
if (!SubRCAndSubRegRC)
1921+
return nullptr;
1922+
1923+
return SubRCAndSubRegRC->second;
1924+
}
1925+
1926+
if (InstName == "SUBREG_TO_REG") {
1927+
// (outs $super_dst), (ins $super_src, $sub_src, $sub_idx)
1928+
// Find a register class that supports both the specified sub-register
1929+
// index and the type of the instruction's result.
1930+
return inferSuperRegisterClass(N.getExtType(0), N.getChild(2));
18831931
}
18841932

18851933
// Handle destination record types that we can safely infer a register class
18861934
// from.
1887-
const auto &DstIOperand = Inst.Operands[0];
1935+
const auto &DstIOperand = Inst.Operands[ResIdx];
18881936
const Record *DstIOpRec = DstIOperand.Rec;
1889-
if (DstIOpRec->isSubClassOf("RegisterOperand")) {
1890-
DstIOpRec = DstIOpRec->getValueAsDef("RegClass");
1891-
const CodeGenRegisterClass &RC = Target.getRegisterClass(DstIOpRec);
1892-
return &RC;
1893-
}
1937+
if (DstIOpRec->isSubClassOf("RegisterOperand"))
1938+
return &Target.getRegisterClass(DstIOpRec->getValueAsDef("RegClass"));
18941939

1895-
if (DstIOpRec->isSubClassOf("RegisterClass")) {
1896-
const CodeGenRegisterClass &RC = Target.getRegisterClass(DstIOpRec);
1897-
return &RC;
1898-
}
1940+
if (DstIOpRec->isSubClassOf("RegisterClass"))
1941+
return &Target.getRegisterClass(DstIOpRec);
18991942

19001943
return nullptr;
19011944
}
@@ -2043,8 +2086,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
20432086
if (!DstOp->isSubClassOf("Instruction"))
20442087
return failedImport("Pattern operator isn't an instruction");
20452088

2046-
auto &DstI = Target.getInstruction(DstOp);
2047-
StringRef DstIName = DstI.TheDef->getName();
2089+
const CodeGenInstruction &DstI = Target.getInstruction(DstOp);
20482090

20492091
// Count both implicit and explicit defs in the dst instruction.
20502092
// This avoids errors importing patterns that have inherent implicit defs.
@@ -2070,68 +2112,24 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
20702112

20712113
// The root of the match also has constraints on the register bank so that it
20722114
// matches the result instruction.
2073-
unsigned OpIdx = 0;
20742115
unsigned N = std::min(DstExpDefs, SrcNumDefs);
20752116
for (unsigned I = 0; I < N; ++I) {
2076-
const TypeSetByHwMode &VTy = Src.getExtType(I);
2117+
const auto &DstIOperand = DstI.Operands[I];
20772118

2078-
const auto &DstIOperand = DstI.Operands[OpIdx];
2079-
PointerUnion<const Record *, const CodeGenRegisterClass *> MatchedRC =
2080-
DstIOperand.Rec;
2081-
if (DstIName == "COPY_TO_REGCLASS") {
2082-
MatchedRC = getInitValueAsRegClass(Dst.getChild(1).getLeafValue());
2083-
2084-
if (MatchedRC.isNull())
2085-
return failedImport(
2086-
"COPY_TO_REGCLASS operand #1 isn't a register class");
2087-
} else if (DstIName == "REG_SEQUENCE") {
2088-
MatchedRC = getInitValueAsRegClass(Dst.getChild(0).getLeafValue());
2089-
if (MatchedRC.isNull())
2090-
return failedImport("REG_SEQUENCE operand #0 isn't a register class");
2091-
} else if (DstIName == "EXTRACT_SUBREG") {
2092-
const CodeGenRegisterClass *InferredClass =
2093-
inferRegClassFromPattern(Dst.getChild(0));
2094-
if (!InferredClass)
2095-
return failedImport(
2096-
"Could not infer class for EXTRACT_SUBREG operand #0");
2097-
2098-
// We can assume that a subregister is in the same bank as it's super
2099-
// register.
2100-
MatchedRC = InferredClass->getDef();
2101-
} else if (DstIName == "INSERT_SUBREG") {
2102-
const CodeGenRegisterClass *MaybeSuperClass =
2103-
inferSuperRegisterClassForNode(VTy, Dst.getChild(0), Dst.getChild(2));
2104-
if (!MaybeSuperClass)
2105-
return failedImport(
2106-
"Cannot infer register class for INSERT_SUBREG operand #0");
2107-
// Move to the next pattern here, because the register class we found
2108-
// doesn't necessarily have a record associated with it. So, we can't
2109-
// set DstIOpRec using this.
2110-
MatchedRC = MaybeSuperClass;
2111-
} else if (DstIName == "SUBREG_TO_REG") {
2112-
const CodeGenRegisterClass *MaybeRegClass =
2113-
inferSuperRegisterClass(VTy, Dst.getChild(2));
2114-
if (!MaybeRegClass)
2115-
return failedImport(
2116-
"Cannot infer register class for SUBREG_TO_REG operand #0");
2117-
MatchedRC = MaybeRegClass;
2118-
} else if (cast<const Record *>(MatchedRC)->isSubClassOf("RegisterOperand"))
2119-
MatchedRC = cast<const Record *>(MatchedRC)->getValueAsDef("RegClass");
2120-
else if (!cast<const Record *>(MatchedRC)->isSubClassOf("RegisterClass"))
2121-
return failedImport("Dst MI def isn't a register class" + to_string(Dst));
2122-
2123-
OperandMatcher &OM = InsnMatcher.getOperand(OpIdx);
2119+
OperandMatcher &OM = InsnMatcher.getOperand(I);
21242120
// The operand names declared in the DstI instruction are unrelated to
21252121
// those used in pattern's source and destination DAGs, so mangle the
21262122
// former to prevent implicitly adding unexpected
21272123
// GIM_CheckIsSameOperand predicates by the defineOperand method.
21282124
OM.setSymbolicName(getMangledRootDefName(DstIOperand.Name));
21292125
M.defineOperand(OM.getSymbolicName(), OM);
2130-
if (auto *R = dyn_cast<const Record *>(MatchedRC))
2131-
MatchedRC = &Target.getRegisterClass(R);
2132-
OM.addPredicate<RegisterBankOperandMatcher>(
2133-
*cast<const CodeGenRegisterClass *>(MatchedRC));
2134-
++OpIdx;
2126+
2127+
const CodeGenRegisterClass *RC =
2128+
inferRegClassFromInstructionPattern(Dst, I);
2129+
if (!RC)
2130+
return failedImport("Could not infer register class for result #" +
2131+
Twine(I) + " from pattern " + to_string(Dst));
2132+
OM.addPredicate<RegisterBankOperandMatcher>(*RC);
21352133
}
21362134

21372135
auto DstMIBuilderOrError =

0 commit comments

Comments
 (0)