@@ -441,26 +441,31 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
441441 const CodeGenRegisterClass *
442442 inferSuperRegisterClassForNode (const TypeSetByHwMode &Ty,
443443 const TreePatternNode &SuperRegNode,
444- const TreePatternNode &SubRegIdxNode);
444+ const TreePatternNode &SubRegIdxNode) const ;
445445 const CodeGenSubRegIndex *
446- inferSubRegIndexForNode (const TreePatternNode &SubRegIdxNode);
446+ inferSubRegIndexForNode (const TreePatternNode &SubRegIdxNode) const ;
447447
448448 // / Infer a CodeGenRegisterClass which suppoorts \p Ty and \p SubRegIdxNode.
449449 // / Return nullptr if no such class exists.
450450 const CodeGenRegisterClass *
451451 inferSuperRegisterClass (const TypeSetByHwMode &Ty,
452- const TreePatternNode &SubRegIdxNode);
452+ const TreePatternNode &SubRegIdxNode) const ;
453453
454454 // / Return the CodeGenRegisterClass associated with \p Leaf if it has one.
455- const CodeGenRegisterClass *getRegClassFromLeaf (const TreePatternNode &Leaf);
455+ const CodeGenRegisterClass *
456+ getRegClassFromLeaf (const TreePatternNode &Leaf) const ;
456457
457458 // / Return a CodeGenRegisterClass for \p N if one can be found. Return
458459 // / nullptr otherwise.
459460 const CodeGenRegisterClass *
460- inferRegClassFromPattern (const TreePatternNode &N);
461+ inferRegClassFromPattern (const TreePatternNode &N) const ;
462+
463+ const CodeGenRegisterClass *
464+ inferRegClassFromInstructionPattern (const TreePatternNode &N,
465+ unsigned ResIdx) const ;
461466
462467 Error constrainOperands (action_iterator InsertPt, RuleMatcher &M,
463- unsigned InsnID, const TreePatternNode &Dst);
468+ unsigned InsnID, const TreePatternNode &Dst) const ;
464469
465470 // / Return the size of the MemoryVT in this predicate, if possible.
466471 std::optional<unsigned >
@@ -1715,7 +1720,7 @@ Error GlobalISelEmitter::importImplicitDefRenderers(
17151720
17161721Error GlobalISelEmitter::constrainOperands (action_iterator InsertPt,
17171722 RuleMatcher &M, unsigned InsnID,
1718- const TreePatternNode &Dst) {
1723+ const TreePatternNode &Dst) const {
17191724 const Record *DstOp = Dst.getOperator ();
17201725 const CodeGenInstruction &DstI = Target.getInstruction (DstOp);
17211726 StringRef DstIName = DstI.TheDef ->getName ();
@@ -1828,7 +1833,7 @@ Error GlobalISelEmitter::constrainOperands(action_iterator InsertPt,
18281833}
18291834
18301835const CodeGenRegisterClass *
1831- GlobalISelEmitter::getRegClassFromLeaf (const TreePatternNode &Leaf) {
1836+ GlobalISelEmitter::getRegClassFromLeaf (const TreePatternNode &Leaf) const {
18321837 assert (Leaf.isLeaf () && " Expected leaf?" );
18331838 const Record *RCRec = getInitValueAsRegClass (Leaf.getLeafValue ());
18341839 if (!RCRec)
@@ -1837,7 +1842,7 @@ GlobalISelEmitter::getRegClassFromLeaf(const TreePatternNode &Leaf) {
18371842}
18381843
18391844const CodeGenRegisterClass *
1840- GlobalISelEmitter::inferRegClassFromPattern (const TreePatternNode &N) {
1845+ GlobalISelEmitter::inferRegClassFromPattern (const TreePatternNode &N) const {
18411846 if (N.isLeaf ())
18421847 return getRegClassFromLeaf (N);
18431848
@@ -1856,52 +1861,91 @@ GlobalISelEmitter::inferRegClassFromPattern(const TreePatternNode &N) {
18561861
18571862 // Don't want to try and infer things when there could potentially be more
18581863 // than one candidate register class.
1859- auto &Inst = Target.getInstruction (OpRec);
1864+ return inferRegClassFromInstructionPattern (N, /* ResIdx=*/ 0 );
1865+ }
1866+
1867+ const CodeGenRegisterClass *
1868+ GlobalISelEmitter::inferRegClassFromInstructionPattern (const TreePatternNode &N,
1869+ unsigned ResIdx) const {
1870+ const CodeGenInstruction &Inst = Target.getInstruction (N.getOperator ());
1871+ assert (ResIdx < Inst.Operands .NumDefs &&
1872+ " Can only infer register class for explicit defs" );
18601873
18611874 // Handle any special-case instructions which we can safely infer register
18621875 // classes from.
18631876 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 );
1877+ if (InstName == " REG_SEQUENCE" ) {
1878+ // (outs $super_dst), (ins $dst_regclass, variable_ops)
1879+ // Destination register class is explicitly specified by the first operand.
1880+ const TreePatternNode &RCChild = N.getChild (0 );
1881+ if (!RCChild.isLeaf ())
1882+ return nullptr ;
1883+ return getRegClassFromLeaf (RCChild);
1884+ }
1885+
1886+ if (InstName == " COPY_TO_REGCLASS" ) {
1887+ // (outs $dst), (ins $src, $dst_regclass)
1888+ // Destination register class is explicitly specified by the second operand.
1889+ const TreePatternNode &RCChild = N.getChild (1 );
18691890 if (!RCChild.isLeaf ())
18701891 return nullptr ;
18711892 return getRegClassFromLeaf (RCChild);
18721893 }
1894+
18731895 if (InstName == " INSERT_SUBREG" ) {
1896+ // (outs $super_dst), (ins $super_src, $sub_src, $sub_idx);
1897+ // If we can infer the register class for the first operand, use that.
1898+ // Otherwise, find a register class that supports both the specified
1899+ // sub-register index and the type of the instruction's result.
18741900 const TreePatternNode &Child0 = N.getChild (0 );
18751901 assert (Child0.getNumTypes () == 1 && " Unexpected number of types!" );
1876- const TypeSetByHwMode &VTy = Child0 .getExtType (0 );
1877- return inferSuperRegisterClassForNode (VTy, Child0, N.getChild (2 ));
1902+ return inferSuperRegisterClassForNode (N .getExtType (0 ), Child0,
1903+ N.getChild (2 ));
18781904 }
1905+
18791906 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 ));
1907+ // (outs $sub_dst), (ins $super_src, $sub_idx)
1908+ // Find a register class that can be used for a sub-register copy from
1909+ // the specified source at the specified sub-register index.
1910+ const CodeGenRegisterClass *SuperRC =
1911+ inferRegClassFromPattern (N.getChild (0 ));
1912+ if (!SuperRC)
1913+ return nullptr ;
1914+
1915+ const CodeGenSubRegIndex *SubIdx = inferSubRegIndexForNode (N.getChild (1 ));
1916+ if (!SubIdx)
1917+ return nullptr ;
1918+
1919+ const auto SubRCAndSubRegRC =
1920+ SuperRC->getMatchingSubClassWithSubRegs (CGRegs, SubIdx);
1921+ if (!SubRCAndSubRegRC)
1922+ return nullptr ;
1923+
1924+ return SubRCAndSubRegRC->second ;
1925+ }
1926+
1927+ if (InstName == " SUBREG_TO_REG" ) {
1928+ // (outs $super_dst), (ins $super_src, $sub_src, $sub_idx)
1929+ // Find a register class that supports both the specified sub-register
1930+ // index and the type of the instruction's result.
1931+ return inferSuperRegisterClass (N.getExtType (0 ), N.getChild (2 ));
18831932 }
18841933
18851934 // Handle destination record types that we can safely infer a register class
18861935 // from.
1887- const auto &DstIOperand = Inst.Operands [0 ];
1936+ const auto &DstIOperand = Inst.Operands [ResIdx ];
18881937 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- }
1938+ if (DstIOpRec->isSubClassOf (" RegisterOperand" ))
1939+ return &Target.getRegisterClass (DstIOpRec->getValueAsDef (" RegClass" ));
18941940
1895- if (DstIOpRec->isSubClassOf (" RegisterClass" )) {
1896- const CodeGenRegisterClass &RC = Target.getRegisterClass (DstIOpRec);
1897- return &RC;
1898- }
1941+ if (DstIOpRec->isSubClassOf (" RegisterClass" ))
1942+ return &Target.getRegisterClass (DstIOpRec);
18991943
19001944 return nullptr ;
19011945}
19021946
19031947const CodeGenRegisterClass *GlobalISelEmitter::inferSuperRegisterClass (
1904- const TypeSetByHwMode &Ty, const TreePatternNode &SubRegIdxNode) {
1948+ const TypeSetByHwMode &Ty, const TreePatternNode &SubRegIdxNode) const {
19051949 // We need a ValueTypeByHwMode for getSuperRegForSubReg.
19061950 if (!Ty.isValueTypeByHwMode (false ))
19071951 return nullptr ;
@@ -1920,7 +1964,7 @@ const CodeGenRegisterClass *GlobalISelEmitter::inferSuperRegisterClass(
19201964
19211965const CodeGenRegisterClass *GlobalISelEmitter::inferSuperRegisterClassForNode (
19221966 const TypeSetByHwMode &Ty, const TreePatternNode &SuperRegNode,
1923- const TreePatternNode &SubRegIdxNode) {
1967+ const TreePatternNode &SubRegIdxNode) const {
19241968 // Check if we already have a defined register class for the super register
19251969 // node. If we do, then we should preserve that rather than inferring anything
19261970 // from the subregister index node. We can assume that whoever wrote the
@@ -1933,7 +1977,7 @@ const CodeGenRegisterClass *GlobalISelEmitter::inferSuperRegisterClassForNode(
19331977}
19341978
19351979const CodeGenSubRegIndex *GlobalISelEmitter::inferSubRegIndexForNode (
1936- const TreePatternNode &SubRegIdxNode) {
1980+ const TreePatternNode &SubRegIdxNode) const {
19371981 if (!SubRegIdxNode.isLeaf ())
19381982 return nullptr ;
19391983
@@ -2043,8 +2087,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
20432087 if (!DstOp->isSubClassOf (" Instruction" ))
20442088 return failedImport (" Pattern operator isn't an instruction" );
20452089
2046- auto &DstI = Target.getInstruction (DstOp);
2047- StringRef DstIName = DstI.TheDef ->getName ();
2090+ const CodeGenInstruction &DstI = Target.getInstruction (DstOp);
20482091
20492092 // Count both implicit and explicit defs in the dst instruction.
20502093 // This avoids errors importing patterns that have inherent implicit defs.
@@ -2070,68 +2113,24 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
20702113
20712114 // The root of the match also has constraints on the register bank so that it
20722115 // matches the result instruction.
2073- unsigned OpIdx = 0 ;
20742116 unsigned N = std::min (DstExpDefs, SrcNumDefs);
20752117 for (unsigned I = 0 ; I < N; ++I) {
2076- const TypeSetByHwMode &VTy = Src. getExtType (I) ;
2118+ const auto &DstIOperand = DstI. Operands [I] ;
20772119
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);
2120+ OperandMatcher &OM = InsnMatcher.getOperand (I);
21242121 // The operand names declared in the DstI instruction are unrelated to
21252122 // those used in pattern's source and destination DAGs, so mangle the
21262123 // former to prevent implicitly adding unexpected
21272124 // GIM_CheckIsSameOperand predicates by the defineOperand method.
21282125 OM.setSymbolicName (getMangledRootDefName (DstIOperand.Name ));
21292126 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;
2127+
2128+ const CodeGenRegisterClass *RC =
2129+ inferRegClassFromInstructionPattern (Dst, I);
2130+ if (!RC)
2131+ return failedImport (" Could not infer register class for result #" +
2132+ Twine (I) + " from pattern " + to_string (Dst));
2133+ OM.addPredicate <RegisterBankOperandMatcher>(*RC);
21352134 }
21362135
21372136 auto DstMIBuilderOrError =
0 commit comments