@@ -460,6 +460,9 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
460460 std::optional<const CodeGenRegisterClass *>
461461 inferRegClassFromPattern (const TreePatternNode &N);
462462
463+ Error constrainOperands (action_iterator InsertPt, RuleMatcher &M,
464+ unsigned InsnID, const TreePatternNode &Dst);
465+
463466 // / Return the size of the MemoryVT in this predicate, if possible.
464467 std::optional<unsigned >
465468 getMemSizeBitsFromPredicate (const TreePredicateFn &Predicate);
@@ -1409,103 +1412,10 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
14091412 if (auto Error = InsertPtOrError.takeError ())
14101413 return std::move (Error);
14111414
1412- // We need to make sure that when we import an INSERT_SUBREG as a
1413- // subinstruction that it ends up being constrained to the correct super
1414- // register and subregister classes.
1415- auto OpName = Target.getInstruction (Dst.getOperator ()).TheDef ->getName ();
1416- if (OpName == " INSERT_SUBREG" ) {
1417- auto SubClass = inferRegClassFromPattern (Dst.getChild (1 ));
1418- if (!SubClass)
1419- return failedImport (
1420- " Cannot infer register class from INSERT_SUBREG operand #1" );
1421- std::optional<const CodeGenRegisterClass *> SuperClass =
1422- inferSuperRegisterClassForNode (Dst.getExtType (0 ), Dst.getChild (0 ),
1423- Dst.getChild (2 ));
1424- if (!SuperClass)
1425- return failedImport (
1426- " Cannot infer register class for INSERT_SUBREG operand #0" );
1427- // The destination and the super register source of an INSERT_SUBREG must
1428- // be the same register class.
1429- M.insertAction <ConstrainOperandToRegClassAction>(
1430- InsertPt, DstMIBuilder.getInsnID (), 0 , **SuperClass);
1431- M.insertAction <ConstrainOperandToRegClassAction>(
1432- InsertPt, DstMIBuilder.getInsnID (), 1 , **SuperClass);
1433- M.insertAction <ConstrainOperandToRegClassAction>(
1434- InsertPt, DstMIBuilder.getInsnID (), 2 , **SubClass);
1435- return InsertPtOrError.get ();
1436- }
1437-
1438- if (OpName == " EXTRACT_SUBREG" ) {
1439- // EXTRACT_SUBREG selects into a subregister COPY but unlike most
1440- // instructions, the result register class is controlled by the
1441- // subregisters of the operand. As a result, we must constrain the result
1442- // class rather than check that it's already the right one.
1443- auto SuperClass = inferRegClassFromPattern (Dst.getChild (0 ));
1444- if (!SuperClass)
1445- return failedImport (
1446- " Cannot infer register class from EXTRACT_SUBREG operand #0" );
1447-
1448- auto SubIdx = inferSubRegIndexForNode (Dst.getChild (1 ));
1449- if (!SubIdx)
1450- return failedImport (" EXTRACT_SUBREG child #1 is not a subreg index" );
1451-
1452- const auto SrcRCDstRCPair =
1453- (*SuperClass)->getMatchingSubClassWithSubRegs (CGRegs, *SubIdx);
1454- assert (SrcRCDstRCPair->second && " Couldn't find a matching subclass" );
1455- M.insertAction <ConstrainOperandToRegClassAction>(
1456- InsertPt, DstMIBuilder.getInsnID (), 0 , *SrcRCDstRCPair->second );
1457- M.insertAction <ConstrainOperandToRegClassAction>(
1458- InsertPt, DstMIBuilder.getInsnID (), 1 , *SrcRCDstRCPair->first );
1459-
1460- // We're done with this pattern! It's eligible for GISel emission; return
1461- // it.
1462- return InsertPtOrError.get ();
1463- }
1464-
1465- // Similar to INSERT_SUBREG, we also have to handle SUBREG_TO_REG as a
1466- // subinstruction.
1467- if (OpName == " SUBREG_TO_REG" ) {
1468- auto SubClass = inferRegClassFromPattern (Dst.getChild (1 ));
1469- if (!SubClass)
1470- return failedImport (
1471- " Cannot infer register class from SUBREG_TO_REG child #1" );
1472- auto SuperClass =
1473- inferSuperRegisterClass (Dst.getExtType (0 ), Dst.getChild (2 ));
1474- if (!SuperClass)
1475- return failedImport (
1476- " Cannot infer register class for SUBREG_TO_REG operand #0" );
1477- M.insertAction <ConstrainOperandToRegClassAction>(
1478- InsertPt, DstMIBuilder.getInsnID (), 0 , **SuperClass);
1479- M.insertAction <ConstrainOperandToRegClassAction>(
1480- InsertPt, DstMIBuilder.getInsnID (), 2 , **SubClass);
1481- return InsertPtOrError.get ();
1482- }
1483-
1484- if (OpName == " REG_SEQUENCE" ) {
1485- auto SuperClass = inferRegClassFromPattern (Dst.getChild (0 ));
1486- M.insertAction <ConstrainOperandToRegClassAction>(
1487- InsertPt, DstMIBuilder.getInsnID (), 0 , **SuperClass);
1488-
1489- unsigned Num = Dst.getNumChildren ();
1490- for (unsigned I = 1 ; I != Num; I += 2 ) {
1491- const TreePatternNode &SubRegChild = Dst.getChild (I + 1 );
1492-
1493- auto SubIdx = inferSubRegIndexForNode (SubRegChild);
1494- if (!SubIdx)
1495- return failedImport (" REG_SEQUENCE child is not a subreg index" );
1496-
1497- const auto SrcRCDstRCPair =
1498- (*SuperClass)->getMatchingSubClassWithSubRegs (CGRegs, *SubIdx);
1499- assert (SrcRCDstRCPair->second && " Couldn't find a matching subclass" );
1500- M.insertAction <ConstrainOperandToRegClassAction>(
1501- InsertPt, DstMIBuilder.getInsnID (), I, *SrcRCDstRCPair->second );
1502- }
1503-
1504- return InsertPtOrError.get ();
1505- }
1415+ if (auto Error =
1416+ constrainOperands (InsertPt, M, DstMIBuilder.getInsnID (), Dst))
1417+ return std::move (Error);
15061418
1507- M.insertAction <ConstrainOperandsToDefinitionAction>(InsertPt,
1508- DstMIBuilder.getInsnID ());
15091419 return InsertPtOrError.get ();
15101420}
15111421
@@ -1794,6 +1704,117 @@ Error GlobalISelEmitter::importImplicitDefRenderers(
17941704 return Error::success ();
17951705}
17961706
1707+ Error GlobalISelEmitter::constrainOperands (action_iterator InsertPt,
1708+ RuleMatcher &M, unsigned InsnID,
1709+ const TreePatternNode &Dst) {
1710+ const Record *DstOp = Dst.getOperator ();
1711+ const CodeGenInstruction &DstI = Target.getInstruction (DstOp);
1712+ StringRef DstIName = DstI.TheDef ->getName ();
1713+
1714+ if (DstIName == " COPY_TO_REGCLASS" ) {
1715+ // COPY_TO_REGCLASS does not provide operand constraints itself but the
1716+ // result is constrained to the class given by the second child.
1717+ const Record *DstIOpRec =
1718+ getInitValueAsRegClass (Dst.getChild (1 ).getLeafValue ());
1719+
1720+ if (DstIOpRec == nullptr )
1721+ return failedImport (" COPY_TO_REGCLASS operand #1 isn't a register class" );
1722+
1723+ M.insertAction <ConstrainOperandToRegClassAction>(
1724+ InsertPt, InsnID, 0 , Target.getRegisterClass (DstIOpRec));
1725+ } else if (DstIName == " EXTRACT_SUBREG" ) {
1726+ // (outs unknown:$dst), (ins unknown:$supersrc, i32imm:$subidx)
1727+ auto SuperClass = inferRegClassFromPattern (Dst.getChild (0 ));
1728+ if (!SuperClass)
1729+ return failedImport (
1730+ " Cannot infer register class from EXTRACT_SUBREG operand #0" );
1731+
1732+ auto SubIdx = inferSubRegIndexForNode (Dst.getChild (1 ));
1733+ if (!SubIdx)
1734+ return failedImport (" EXTRACT_SUBREG child #1 is not a subreg index" );
1735+
1736+ // It would be nice to leave this constraint implicit but we're required
1737+ // to pick a register class so constrain the result to a register class
1738+ // that can hold the correct MVT.
1739+ //
1740+ // FIXME: This may introduce an extra copy if the chosen class doesn't
1741+ // actually contain the subregisters.
1742+ const auto SrcRCDstRCPair =
1743+ (*SuperClass)->getMatchingSubClassWithSubRegs (CGRegs, *SubIdx);
1744+ if (!SrcRCDstRCPair) {
1745+ return failedImport (" subreg index is incompatible "
1746+ " with inferred reg class" );
1747+ }
1748+
1749+ assert (SrcRCDstRCPair->second && " Couldn't find a matching subclass" );
1750+ M.insertAction <ConstrainOperandToRegClassAction>(InsertPt, InsnID, 0 ,
1751+ *SrcRCDstRCPair->second );
1752+ M.insertAction <ConstrainOperandToRegClassAction>(InsertPt, InsnID, 1 ,
1753+ *SrcRCDstRCPair->first );
1754+ } else if (DstIName == " INSERT_SUBREG" ) {
1755+ // We need to constrain the destination, a super regsister source, and a
1756+ // subregister source.
1757+ auto SubClass = inferRegClassFromPattern (Dst.getChild (1 ));
1758+ if (!SubClass)
1759+ return failedImport (
1760+ " Cannot infer register class from INSERT_SUBREG operand #1" );
1761+ auto SuperClass = inferSuperRegisterClassForNode (
1762+ Dst.getExtType (0 ), Dst.getChild (0 ), Dst.getChild (2 ));
1763+ if (!SuperClass)
1764+ return failedImport (
1765+ " Cannot infer register class for INSERT_SUBREG operand #0" );
1766+ M.insertAction <ConstrainOperandToRegClassAction>(InsertPt, InsnID, 0 ,
1767+ **SuperClass);
1768+ M.insertAction <ConstrainOperandToRegClassAction>(InsertPt, InsnID, 1 ,
1769+ **SuperClass);
1770+ M.insertAction <ConstrainOperandToRegClassAction>(InsertPt, InsnID, 2 ,
1771+ **SubClass);
1772+ } else if (DstIName == " SUBREG_TO_REG" ) {
1773+ // We need to constrain the destination and subregister source.
1774+ // Attempt to infer the subregister source from the first child. If it has
1775+ // an explicitly given register class, we'll use that. Otherwise, we will
1776+ // fail.
1777+ auto SubClass = inferRegClassFromPattern (Dst.getChild (1 ));
1778+ if (!SubClass)
1779+ return failedImport (
1780+ " Cannot infer register class from SUBREG_TO_REG child #1" );
1781+ // We don't have a child to look at that might have a super register node.
1782+ auto SuperClass =
1783+ inferSuperRegisterClass (Dst.getExtType (0 ), Dst.getChild (2 ));
1784+ if (!SuperClass)
1785+ return failedImport (
1786+ " Cannot infer register class for SUBREG_TO_REG operand #0" );
1787+ M.insertAction <ConstrainOperandToRegClassAction>(InsertPt, InsnID, 0 ,
1788+ **SuperClass);
1789+ M.insertAction <ConstrainOperandToRegClassAction>(InsertPt, InsnID, 2 ,
1790+ **SubClass);
1791+ } else if (DstIName == " REG_SEQUENCE" ) {
1792+ auto SuperClass = inferRegClassFromPattern (Dst.getChild (0 ));
1793+
1794+ M.insertAction <ConstrainOperandToRegClassAction>(InsertPt, InsnID, 0 ,
1795+ **SuperClass);
1796+
1797+ unsigned Num = Dst.getNumChildren ();
1798+ for (unsigned I = 1 ; I != Num; I += 2 ) {
1799+ const TreePatternNode &SubRegChild = Dst.getChild (I + 1 );
1800+
1801+ auto SubIdx = inferSubRegIndexForNode (SubRegChild);
1802+ if (!SubIdx)
1803+ return failedImport (" REG_SEQUENCE child is not a subreg index" );
1804+
1805+ const auto SrcRCDstRCPair =
1806+ (*SuperClass)->getMatchingSubClassWithSubRegs (CGRegs, *SubIdx);
1807+
1808+ M.insertAction <ConstrainOperandToRegClassAction>(InsertPt, InsnID, I,
1809+ *SrcRCDstRCPair->second );
1810+ }
1811+ } else {
1812+ M.insertAction <ConstrainOperandsToDefinitionAction>(InsertPt, InsnID);
1813+ }
1814+
1815+ return Error::success ();
1816+ }
1817+
17971818std::optional<const CodeGenRegisterClass *>
17981819GlobalISelEmitter::getRegClassFromLeaf (const TreePatternNode &Leaf) {
17991820 assert (Leaf.isLeaf () && " Expected leaf?" );
@@ -2123,106 +2144,9 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
21232144
21242145 // Constrain the registers to classes. This is normally derived from the
21252146 // emitted instruction but a few instructions require special handling.
2126- if (DstIName == " COPY_TO_REGCLASS" ) {
2127- // COPY_TO_REGCLASS does not provide operand constraints itself but the
2128- // result is constrained to the class given by the second child.
2129- const Record *DstIOpRec =
2130- getInitValueAsRegClass (Dst.getChild (1 ).getLeafValue ());
2131-
2132- if (DstIOpRec == nullptr )
2133- return failedImport (" COPY_TO_REGCLASS operand #1 isn't a register class" );
2134-
2135- M.addAction <ConstrainOperandToRegClassAction>(
2136- 0 , 0 , Target.getRegisterClass (DstIOpRec));
2137- } else if (DstIName == " EXTRACT_SUBREG" ) {
2138- auto SuperClass = inferRegClassFromPattern (Dst.getChild (0 ));
2139- if (!SuperClass)
2140- return failedImport (
2141- " Cannot infer register class from EXTRACT_SUBREG operand #0" );
2142-
2143- auto SubIdx = inferSubRegIndexForNode (Dst.getChild (1 ));
2144- if (!SubIdx)
2145- return failedImport (" EXTRACT_SUBREG child #1 is not a subreg index" );
2146-
2147- // It would be nice to leave this constraint implicit but we're required
2148- // to pick a register class so constrain the result to a register class
2149- // that can hold the correct MVT.
2150- //
2151- // FIXME: This may introduce an extra copy if the chosen class doesn't
2152- // actually contain the subregisters.
2153- assert (Src.getExtTypes ().size () == 1 &&
2154- " Expected Src of EXTRACT_SUBREG to have one result type" );
2155-
2156- const auto SrcRCDstRCPair =
2157- (*SuperClass)->getMatchingSubClassWithSubRegs (CGRegs, *SubIdx);
2158- if (!SrcRCDstRCPair) {
2159- return failedImport (" subreg index is incompatible "
2160- " with inferred reg class" );
2161- }
2162-
2163- assert (SrcRCDstRCPair->second && " Couldn't find a matching subclass" );
2164- M.addAction <ConstrainOperandToRegClassAction>(0 , 0 ,
2165- *SrcRCDstRCPair->second );
2166- M.addAction <ConstrainOperandToRegClassAction>(0 , 1 , *SrcRCDstRCPair->first );
2167- } else if (DstIName == " INSERT_SUBREG" ) {
2168- assert (Src.getExtTypes ().size () == 1 &&
2169- " Expected Src of INSERT_SUBREG to have one result type" );
2170- // We need to constrain the destination, a super regsister source, and a
2171- // subregister source.
2172- auto SubClass = inferRegClassFromPattern (Dst.getChild (1 ));
2173- if (!SubClass)
2174- return failedImport (
2175- " Cannot infer register class from INSERT_SUBREG operand #1" );
2176- auto SuperClass = inferSuperRegisterClassForNode (
2177- Src.getExtType (0 ), Dst.getChild (0 ), Dst.getChild (2 ));
2178- if (!SuperClass)
2179- return failedImport (
2180- " Cannot infer register class for INSERT_SUBREG operand #0" );
2181- M.addAction <ConstrainOperandToRegClassAction>(0 , 0 , **SuperClass);
2182- M.addAction <ConstrainOperandToRegClassAction>(0 , 1 , **SuperClass);
2183- M.addAction <ConstrainOperandToRegClassAction>(0 , 2 , **SubClass);
2184- } else if (DstIName == " SUBREG_TO_REG" ) {
2185- // We need to constrain the destination and subregister source.
2186- assert (Src.getExtTypes ().size () == 1 &&
2187- " Expected Src of SUBREG_TO_REG to have one result type" );
2188-
2189- // Attempt to infer the subregister source from the first child. If it has
2190- // an explicitly given register class, we'll use that. Otherwise, we will
2191- // fail.
2192- auto SubClass = inferRegClassFromPattern (Dst.getChild (1 ));
2193- if (!SubClass)
2194- return failedImport (
2195- " Cannot infer register class from SUBREG_TO_REG child #1" );
2196- // We don't have a child to look at that might have a super register node.
2197- auto SuperClass =
2198- inferSuperRegisterClass (Src.getExtType (0 ), Dst.getChild (2 ));
2199- if (!SuperClass)
2200- return failedImport (
2201- " Cannot infer register class for SUBREG_TO_REG operand #0" );
2202- M.addAction <ConstrainOperandToRegClassAction>(0 , 0 , **SuperClass);
2203- M.addAction <ConstrainOperandToRegClassAction>(0 , 2 , **SubClass);
2204- } else if (DstIName == " REG_SEQUENCE" ) {
2205- auto SuperClass = inferRegClassFromPattern (Dst.getChild (0 ));
2206-
2207- M.addAction <ConstrainOperandToRegClassAction>(0 , 0 , **SuperClass);
2208-
2209- unsigned Num = Dst.getNumChildren ();
2210- for (unsigned I = 1 ; I != Num; I += 2 ) {
2211- TreePatternNode &SubRegChild = Dst.getChild (I + 1 );
2212-
2213- auto SubIdx = inferSubRegIndexForNode (SubRegChild);
2214- if (!SubIdx)
2215- return failedImport (" REG_SEQUENCE child is not a subreg index" );
2216-
2217- const auto SrcRCDstRCPair =
2218- (*SuperClass)->getMatchingSubClassWithSubRegs (CGRegs, *SubIdx);
2219-
2220- M.addAction <ConstrainOperandToRegClassAction>(0 , I,
2221- *SrcRCDstRCPair->second );
2222- }
2223- } else {
2224- M.addAction <ConstrainOperandsToDefinitionAction>(0 );
2225- }
2147+ if (auto Error =
2148+ constrainOperands (M.actions_end (), M, DstMIBuilder.getInsnID (), Dst))
2149+ return std::move (Error);
22262150
22272151 // Erase the root.
22282152 unsigned RootInsnID = M.getInsnVarID (InsnMatcher);
0 commit comments