@@ -460,6 +460,9 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
460
460
std::optional<const CodeGenRegisterClass *>
461
461
inferRegClassFromPattern (const TreePatternNode &N);
462
462
463
+ Error constrainOperands (action_iterator InsertPt, RuleMatcher &M,
464
+ unsigned InsnID, const TreePatternNode &Dst);
465
+
463
466
// / Return the size of the MemoryVT in this predicate, if possible.
464
467
std::optional<unsigned >
465
468
getMemSizeBitsFromPredicate (const TreePredicateFn &Predicate);
@@ -1409,103 +1412,10 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
1409
1412
if (auto Error = InsertPtOrError.takeError ())
1410
1413
return std::move (Error);
1411
1414
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);
1506
1418
1507
- M.insertAction <ConstrainOperandsToDefinitionAction>(InsertPt,
1508
- DstMIBuilder.getInsnID ());
1509
1419
return InsertPtOrError.get ();
1510
1420
}
1511
1421
@@ -1794,6 +1704,117 @@ Error GlobalISelEmitter::importImplicitDefRenderers(
1794
1704
return Error::success ();
1795
1705
}
1796
1706
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
+
1797
1818
std::optional<const CodeGenRegisterClass *>
1798
1819
GlobalISelEmitter::getRegClassFromLeaf (const TreePatternNode &Leaf) {
1799
1820
assert (Leaf.isLeaf () && " Expected leaf?" );
@@ -2123,106 +2144,9 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
2123
2144
2124
2145
// Constrain the registers to classes. This is normally derived from the
2125
2146
// 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);
2226
2150
2227
2151
// Erase the root.
2228
2152
unsigned RootInsnID = M.getInsnVarID (InsnMatcher);
0 commit comments