@@ -832,7 +832,13 @@ class InstructionOperandMatcher : public OperandPredicateMatcher {
832
832
// ===- Actions ------------------------------------------------------------===//
833
833
class OperandRenderer {
834
834
public:
835
- enum RendererKind { OR_Copy, OR_Imm, OR_Register, OR_ComplexPattern };
835
+ enum RendererKind {
836
+ OR_Copy,
837
+ OR_CopySubReg,
838
+ OR_Imm,
839
+ OR_Register,
840
+ OR_ComplexPattern
841
+ };
836
842
837
843
protected:
838
844
RendererKind Kind;
@@ -877,6 +883,42 @@ class CopyRenderer : public OperandRenderer {
877
883
}
878
884
};
879
885
886
+ // / A CopySubRegRenderer emits code to copy a single register operand from an
887
+ // / existing instruction to the one being built and indicate that only a
888
+ // / subregister should be copied.
889
+ class CopySubRegRenderer : public OperandRenderer {
890
+ protected:
891
+ // / The matcher for the instruction that this operand is copied from.
892
+ // / This provides the facility for looking up an a operand by it's name so
893
+ // / that it can be used as a source for the instruction being built.
894
+ const InstructionMatcher &Matched;
895
+ // / The name of the operand.
896
+ const StringRef SymbolicName;
897
+ // / The subregister to extract.
898
+ const CodeGenSubRegIndex *SubReg;
899
+
900
+ public:
901
+ CopySubRegRenderer (const InstructionMatcher &Matched, StringRef SymbolicName,
902
+ const CodeGenSubRegIndex *SubReg)
903
+ : OperandRenderer(OR_CopySubReg), Matched(Matched),
904
+ SymbolicName (SymbolicName), SubReg(SubReg) {}
905
+
906
+ static bool classof (const OperandRenderer *R) {
907
+ return R->getKind () == OR_CopySubReg;
908
+ }
909
+
910
+ const StringRef getSymbolicName () const { return SymbolicName; }
911
+
912
+ void emitCxxRenderStmts (raw_ostream &OS, RuleMatcher &Rule) const override {
913
+ const OperandMatcher &Operand = Matched.getOperand (SymbolicName);
914
+ StringRef InsnVarName =
915
+ Rule.getInsnVarName (Operand.getInstructionMatcher ());
916
+ std::string OperandExpr = Operand.getOperandExpr (InsnVarName);
917
+ OS << " MIB.addReg(" << OperandExpr << " .getReg() /*" << SymbolicName
918
+ << " */, 0, " << SubReg->EnumValue << " );\n " ;
919
+ }
920
+ };
921
+
880
922
// / Adds a specific physical register to the instruction being built.
881
923
// / This is typically useful for WZR/XZR on AArch64.
882
924
class AddRegisterRenderer : public OperandRenderer {
@@ -1292,6 +1334,7 @@ class GlobalISelEmitter {
1292
1334
const RecordKeeper &RK;
1293
1335
const CodeGenDAGPatterns CGP;
1294
1336
const CodeGenTarget &Target;
1337
+ CodeGenRegBank CGRegs;
1295
1338
1296
1339
// / Keep track of the equivalence between SDNodes and Instruction.
1297
1340
// / This is defined using 'GINodeEquiv' in the target description.
@@ -1315,9 +1358,9 @@ class GlobalISelEmitter {
1315
1358
Error importChildMatcher (InstructionMatcher &InsnMatcher,
1316
1359
const TreePatternNode *SrcChild, unsigned OpIdx,
1317
1360
unsigned &TempOpIdx) const ;
1318
- Expected<BuildMIAction &> createAndImportInstructionRenderer (
1319
- RuleMatcher &M, const TreePatternNode *Dst,
1320
- const InstructionMatcher &InsnMatcher) const ;
1361
+ Expected<BuildMIAction &>
1362
+ createAndImportInstructionRenderer ( RuleMatcher &M, const TreePatternNode *Dst,
1363
+ const InstructionMatcher &InsnMatcher);
1321
1364
Error importExplicitUseRenderer (BuildMIAction &DstMIBuilder,
1322
1365
TreePatternNode *DstChild,
1323
1366
const InstructionMatcher &InsnMatcher) const ;
@@ -1354,7 +1397,7 @@ const CodeGenInstruction *GlobalISelEmitter::findNodeEquiv(Record *N) const {
1354
1397
}
1355
1398
1356
1399
GlobalISelEmitter::GlobalISelEmitter (RecordKeeper &RK)
1357
- : RK(RK), CGP(RK), Target(CGP.getTargetInfo()) {}
1400
+ : RK(RK), CGP(RK), Target(CGP.getTargetInfo()), CGRegs(RK) {}
1358
1401
1359
1402
// ===- Emitter ------------------------------------------------------------===//
1360
1403
@@ -1585,7 +1628,7 @@ Error GlobalISelEmitter::importExplicitUseRenderer(
1585
1628
1586
1629
Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer (
1587
1630
RuleMatcher &M, const TreePatternNode *Dst,
1588
- const InstructionMatcher &InsnMatcher) const {
1631
+ const InstructionMatcher &InsnMatcher) {
1589
1632
Record *DstOp = Dst->getOperator ();
1590
1633
if (!DstOp->isSubClassOf (" Instruction" )) {
1591
1634
if (DstOp->isSubClassOf (" ValueType" ))
@@ -1597,13 +1640,17 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
1597
1640
1598
1641
unsigned DstINumUses = DstI->Operands .size () - DstI->Operands .NumDefs ;
1599
1642
unsigned ExpectedDstINumUses = Dst->getNumChildren ();
1643
+ bool IsExtractSubReg = false ;
1600
1644
1601
1645
// COPY_TO_REGCLASS is just a copy with a ConstrainOperandToRegClassAction
1602
- // attached.
1646
+ // attached. Similarly for EXTRACT_SUBREG except that's a subregister copy.
1603
1647
if (DstI->TheDef ->getName () == " COPY_TO_REGCLASS" ) {
1604
1648
DstI = &Target.getInstruction (RK.getDef (" COPY" ));
1605
1649
DstINumUses--; // Ignore the class constraint.
1606
1650
ExpectedDstINumUses--;
1651
+ } else if (DstI->TheDef ->getName () == " EXTRACT_SUBREG" ) {
1652
+ DstI = &Target.getInstruction (RK.getDef (" COPY" ));
1653
+ IsExtractSubReg = true ;
1607
1654
}
1608
1655
1609
1656
auto &DstMIBuilder = M.addAction <BuildMIAction>(" NewI" , DstI, InsnMatcher);
@@ -1614,6 +1661,32 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
1614
1661
DstMIBuilder.addRenderer <CopyRenderer>(InsnMatcher, DstIOperand.Name );
1615
1662
}
1616
1663
1664
+ // EXTRACT_SUBREG needs to use a subregister COPY.
1665
+ if (IsExtractSubReg) {
1666
+ if (!Dst->getChild (0 )->isLeaf ())
1667
+ return failedImport (" EXTRACT_SUBREG child #1 is not a leaf" );
1668
+
1669
+ if (DefInit *SubRegInit = dyn_cast<DefInit>(Dst->getChild (1 )->getLeafValue ())) {
1670
+ CodeGenRegisterClass *RC = CGRegs.getRegClass (
1671
+ getInitValueAsRegClass (Dst->getChild (0 )->getLeafValue ()));
1672
+ CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx (SubRegInit->getDef ());
1673
+
1674
+ const auto &SrcRCDstRCPair =
1675
+ RC->getMatchingSubClassWithSubRegs (CGRegs, SubIdx);
1676
+ if (SrcRCDstRCPair.hasValue ()) {
1677
+ assert (SrcRCDstRCPair->second && " Couldn't find a matching subclass" );
1678
+ if (SrcRCDstRCPair->first != RC)
1679
+ return failedImport (" EXTRACT_SUBREG requires an additional COPY" );
1680
+ }
1681
+
1682
+ DstMIBuilder.addRenderer <CopySubRegRenderer>(
1683
+ InsnMatcher, Dst->getChild (0 )->getName (), SubIdx);
1684
+ return DstMIBuilder;
1685
+ }
1686
+
1687
+ return failedImport (" EXTRACT_SUBREG child #1 is not a subreg index" );
1688
+ }
1689
+
1617
1690
// Render the explicit uses.
1618
1691
unsigned Child = 0 ;
1619
1692
unsigned NumDefaultOps = 0 ;
@@ -1740,6 +1813,16 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
1740
1813
if (DstIOpRec == nullptr )
1741
1814
return failedImport (
1742
1815
" COPY_TO_REGCLASS operand #1 isn't a register class" );
1816
+ } else if (DstI.TheDef ->getName () == " EXTRACT_SUBREG" ) {
1817
+ if (!Dst->getChild (0 )->isLeaf ())
1818
+ return failedImport (" EXTRACT_SUBREG operand #0 isn't a leaf" );
1819
+
1820
+ // We can assume that a subregister is in the same bank as it's super register.
1821
+ DstIOpRec = getInitValueAsRegClass (Dst->getChild (0 )->getLeafValue ());
1822
+
1823
+ if (DstIOpRec == nullptr )
1824
+ return failedImport (
1825
+ " EXTRACT_SUBREG operand #0 isn't a register class" );
1743
1826
} else if (DstIOpRec->isSubClassOf (" RegisterOperand" ))
1744
1827
DstIOpRec = DstIOpRec->getValueAsDef (" RegClass" );
1745
1828
else if (!DstIOpRec->isSubClassOf (" RegisterClass" ))
@@ -1776,8 +1859,58 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
1776
1859
1777
1860
M.addAction <ConstrainOperandToRegClassAction>(
1778
1861
" NewI" , 0 , Target.getRegisterClass (DstIOpRec));
1779
- } else
1780
- M.addAction <ConstrainOperandsToDefinitionAction>(" NewI" );
1862
+
1863
+ // We're done with this pattern! It's eligible for GISel emission; return
1864
+ // it.
1865
+ ++NumPatternImported;
1866
+ return std::move (M);
1867
+ }
1868
+
1869
+ if (DstI.TheDef ->getName () == " EXTRACT_SUBREG" ) {
1870
+ // EXTRACT_SUBREG selects into a subregister COPY but unlike most
1871
+ // instructions, the result register class is controlled by the
1872
+ // subregisters of the operand. As a result, we must constrain the result
1873
+ // class rather than check that it's already the right one.
1874
+ if (!Dst->getChild (0 )->isLeaf ())
1875
+ return failedImport (" EXTRACT_SUBREG child #1 is not a leaf" );
1876
+
1877
+ if (DefInit *SubRegInit =
1878
+ dyn_cast<DefInit>(Dst->getChild (1 )->getLeafValue ())) {
1879
+ // Constrain the result to the same register bank as the operand.
1880
+ Record *DstIOpRec =
1881
+ getInitValueAsRegClass (Dst->getChild (0 )->getLeafValue ());
1882
+
1883
+ if (DstIOpRec == nullptr )
1884
+ return failedImport (" EXTRACT_SUBREG operand #1 isn't a register class" );
1885
+
1886
+ CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx (SubRegInit->getDef ());
1887
+ CodeGenRegisterClass *SrcRC = CGRegs.getRegClass (
1888
+ getInitValueAsRegClass (Dst->getChild (0 )->getLeafValue ()));
1889
+
1890
+ // It would be nice to leave this constraint implicit but we're required
1891
+ // to pick a register class so constrain the result to a register class
1892
+ // that can hold the correct MVT.
1893
+ //
1894
+ // FIXME: This may introduce an extra copy if the chosen class doesn't
1895
+ // actually contain the subregisters.
1896
+ assert (Src->getExtTypes ().size () == 1 );
1897
+
1898
+ const auto &SrcRCDstRCPair =
1899
+ SrcRC->getMatchingSubClassWithSubRegs (CGRegs, SubIdx);
1900
+ assert (SrcRCDstRCPair->second && " Couldn't find a matching subclass" );
1901
+ M.addAction <ConstrainOperandToRegClassAction>(" NewI" , 0 , *SrcRCDstRCPair->second );
1902
+ M.addAction <ConstrainOperandToRegClassAction>(" NewI" , 1 , *SrcRCDstRCPair->first );
1903
+
1904
+ // We're done with this pattern! It's eligible for GISel emission; return
1905
+ // it.
1906
+ ++NumPatternImported;
1907
+ return std::move (M);
1908
+ }
1909
+
1910
+ return failedImport (" EXTRACT_SUBREG child #1 is not a subreg index" );
1911
+ }
1912
+
1913
+ M.addAction <ConstrainOperandsToDefinitionAction>(" NewI" );
1781
1914
1782
1915
// We're done with this pattern! It's eligible for GISel emission; return it.
1783
1916
++NumPatternImported;
0 commit comments