@@ -398,19 +398,19 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
398398
399399 Expected<BuildMIAction &> createAndImportInstructionRenderer (
400400 RuleMatcher &M, InstructionMatcher &InsnMatcher,
401- const TreePatternNode &Src, const TreePatternNode &Dst);
401+ const TreePatternNode &Src, const TreePatternNode &Dst,
402+ ArrayRef<const Record *> DstPhysDefs);
402403 Expected<action_iterator> createAndImportSubInstructionRenderer (
403404 action_iterator InsertPt, RuleMatcher &M, const TreePatternNode &Dst,
404405 const TreePatternNode &Src, unsigned TempReg);
405406 Expected<action_iterator>
406407 createInstructionRenderer (action_iterator InsertPt, RuleMatcher &M,
407408 const TreePatternNode &Dst);
408409
409- Expected<action_iterator>
410- importExplicitDefRenderers (action_iterator InsertPt, RuleMatcher &M,
411- BuildMIAction &DstMIBuilder,
412- const TreePatternNode &Src,
413- const TreePatternNode &Dst, unsigned Start = 0 );
410+ Expected<action_iterator> importExplicitDefRenderers (
411+ action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
412+ const TreePatternNode &Src, const TreePatternNode &Dst,
413+ ArrayRef<const Record *> DstPhysDefs = {}, unsigned Start = 0 );
414414
415415 Expected<action_iterator> importExplicitUseRenderers (
416416 action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
@@ -421,8 +421,6 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
421421 Error importDefaultOperandRenderers (action_iterator InsertPt, RuleMatcher &M,
422422 BuildMIAction &DstMIBuilder,
423423 const DAGDefaultOperand &DefaultOp) const ;
424- Error importImplicitDefRenderers (BuildMIAction &DstMIBuilder,
425- ArrayRef<const Record *> ImplicitDefs) const ;
426424
427425 // / Analyze pattern \p P, returning a matcher for it if possible.
428426 // / Otherwise, return an Error explaining why we don't support it.
@@ -1348,7 +1346,7 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
13481346
13491347Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer (
13501348 RuleMatcher &M, InstructionMatcher &InsnMatcher, const TreePatternNode &Src,
1351- const TreePatternNode &Dst) {
1349+ const TreePatternNode &Dst, ArrayRef< const Record *> DstPhysDefs ) {
13521350 auto InsertPtOrError = createInstructionRenderer (M.actions_end (), M, Dst);
13531351 if (auto Error = InsertPtOrError.takeError ())
13541352 return std::move (Error);
@@ -1367,9 +1365,9 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
13671365 CopyToPhysRegMIBuilder.addRenderer <CopyPhysRegRenderer>(PhysInput.first );
13681366 }
13691367
1370- if (auto Error =
1371- importExplicitDefRenderers (InsertPt, M, DstMIBuilder, Src, Dst)
1372- .takeError ())
1368+ if (auto Error = importExplicitDefRenderers (InsertPt, M, DstMIBuilder, Src,
1369+ Dst, DstPhysDefs )
1370+ .takeError ())
13731371 return std::move (Error);
13741372
13751373 if (auto Error =
@@ -1399,8 +1397,9 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
13991397
14001398 // Handle additional (ignored) results.
14011399 if (DstMIBuilder.getCGI ()->Operands .NumDefs > 1 ) {
1402- InsertPtOrError = importExplicitDefRenderers (
1403- std::prev (*InsertPtOrError), M, DstMIBuilder, Src, Dst, /* Start=*/ 1 );
1400+ InsertPtOrError =
1401+ importExplicitDefRenderers (std::prev (*InsertPtOrError), M, DstMIBuilder,
1402+ Src, Dst, /* DstPhysDefs=*/ {}, /* Start=*/ 1 );
14041403 if (auto Error = InsertPtOrError.takeError ())
14051404 return std::move (Error);
14061405 }
@@ -1533,19 +1532,29 @@ Expected<action_iterator> GlobalISelEmitter::createInstructionRenderer(
15331532
15341533Expected<action_iterator> GlobalISelEmitter::importExplicitDefRenderers (
15351534 action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
1536- const TreePatternNode &Src, const TreePatternNode &Dst, unsigned Start) {
1535+ const TreePatternNode &Src, const TreePatternNode &Dst,
1536+ ArrayRef<const Record *> DstPhysDefs, unsigned Start) {
15371537 const CodeGenInstruction *DstI = DstMIBuilder.getCGI ();
15381538 const unsigned SrcNumDefs = Src.getExtTypes ().size ();
1539- const unsigned DstNumDefs = DstI->Operands .NumDefs ;
1539+ const unsigned DstNumVirtDefs = DstI->Operands .NumDefs ,
1540+ DstNumDefs = DstNumVirtDefs + DstPhysDefs.size ();
15401541 if (DstNumDefs == 0 )
15411542 return InsertPt;
15421543
15431544 for (unsigned I = Start; I < SrcNumDefs; ++I) {
1544- std::string OpName = getMangledRootDefName (DstI->Operands [I].Name );
1545- // CopyRenderer saves a StringRef, so cannot pass OpName itself -
1546- // let's use a string with an appropriate lifetime.
1547- StringRef PermanentRef = M.getOperandMatcher (OpName).getSymbolicName ();
1548- DstMIBuilder.addRenderer <CopyRenderer>(PermanentRef);
1545+ if (I < DstNumVirtDefs) {
1546+ std::string OpName = getMangledRootDefName (DstI->Operands [I].Name );
1547+ // CopyRenderer saves a StringRef, so cannot pass OpName itself -
1548+ // let's use a string with an appropriate lifetime.
1549+ StringRef PermanentRef = M.getOperandMatcher (OpName).getSymbolicName ();
1550+ DstMIBuilder.addRenderer <CopyRenderer>(PermanentRef);
1551+ } else if (I < DstNumDefs) {
1552+ const auto *PhysReg = DstPhysDefs[I - DstNumVirtDefs];
1553+ DstMIBuilder.addRenderer <CopyPhysRegRenderer>(PhysReg);
1554+ } else {
1555+ return failedImport (" number of defs in src exceeds number of implicit "
1556+ " and explicit defs in dst" );
1557+ }
15491558 }
15501559
15511560 // Some instructions have multiple defs, but are missing a type entry
@@ -1788,13 +1797,6 @@ Error GlobalISelEmitter::importDefaultOperandRenderers(
17881797 return Error::success ();
17891798}
17901799
1791- Error GlobalISelEmitter::importImplicitDefRenderers (
1792- BuildMIAction &DstMIBuilder, ArrayRef<const Record *> ImplicitDefs) const {
1793- if (!ImplicitDefs.empty ())
1794- return failedImport (" Pattern defines a physical register" );
1795- return Error::success ();
1796- }
1797-
17981800std::optional<const CodeGenRegisterClass *>
17991801GlobalISelEmitter::getRegClassFromLeaf (const TreePatternNode &Leaf) {
18001802 assert (Leaf.isLeaf () && " Expected leaf?" );
@@ -2022,11 +2024,9 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
20222024
20232025 auto &DstI = Target.getInstruction (DstOp);
20242026 StringRef DstIName = DstI.TheDef ->getName ();
2025-
2026- // Count both implicit and explicit defs in the dst instruction.
2027- // This avoids errors importing patterns that have inherent implicit defs.
2028- unsigned DstExpDefs = DstI.Operands .NumDefs ,
2029- DstNumDefs = DstI.ImplicitDefs .size () + DstExpDefs,
2027+ const auto &DstPhysDefs = P.getDstRegs ();
2028+ unsigned DstNumVirtDefs = DstI.Operands .NumDefs ,
2029+ DstNumDefs = DstNumVirtDefs + DstPhysDefs.size (),
20302030 SrcNumDefs = Src.getExtTypes ().size ();
20312031 if (DstNumDefs < SrcNumDefs) {
20322032 if (DstNumDefs != 0 )
@@ -2048,13 +2048,13 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
20482048 // The root of the match also has constraints on the register bank so that it
20492049 // matches the result instruction.
20502050 unsigned OpIdx = 0 ;
2051- unsigned N = std::min (DstExpDefs , SrcNumDefs);
2051+ unsigned N = std::min (DstNumDefs , SrcNumDefs);
20522052 for (unsigned I = 0 ; I < N; ++I) {
20532053 const TypeSetByHwMode &VTy = Src.getExtType (I);
20542054
2055- const auto &DstIOperand = DstI.Operands [OpIdx];
20562055 PointerUnion<const Record *, const CodeGenRegisterClass *> MatchedRC =
2057- DstIOperand.Rec ;
2056+ OpIdx < DstNumVirtDefs ? DstI.Operands [OpIdx].Rec
2057+ : DstPhysDefs[OpIdx - DstNumVirtDefs];
20582058 if (DstIName == " COPY_TO_REGCLASS" ) {
20592059 MatchedRC = getInitValueAsRegClass (Dst.getChild (1 ).getLeafValue ());
20602060
@@ -2092,16 +2092,26 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
20922092 MatchedRC = *MaybeRegClass;
20932093 } else if (MatchedRC.get <const Record *>()->isSubClassOf (" RegisterOperand" ))
20942094 MatchedRC = MatchedRC.get <const Record *>()->getValueAsDef (" RegClass" );
2095- else if (!MatchedRC.get <const Record *>()->isSubClassOf (" RegisterClass" ))
2095+ else if (MatchedRC.get <const Record *>()->isSubClassOf (" Register" )) {
2096+ auto MaybeRegClass =
2097+ CGRegs.getRegClassForRegister (MatchedRC.get <const Record *>());
2098+ if (!MaybeRegClass)
2099+ return failedImport (" Cannot infer register class for register" );
2100+ MatchedRC = MaybeRegClass;
2101+ } else if (!MatchedRC.get <const Record *>()->isSubClassOf (" RegisterClass" ))
20962102 return failedImport (" Dst MI def isn't a register class" + to_string (Dst));
20972103
20982104 OperandMatcher &OM = InsnMatcher.getOperand (OpIdx);
20992105 // The operand names declared in the DstI instruction are unrelated to
21002106 // those used in pattern's source and destination DAGs, so mangle the
21012107 // former to prevent implicitly adding unexpected
21022108 // GIM_CheckIsSameOperand predicates by the defineOperand method.
2103- OM.setSymbolicName (getMangledRootDefName (DstIOperand.Name ));
2104- M.defineOperand (OM.getSymbolicName (), OM);
2109+ if (OpIdx < DstNumVirtDefs) {
2110+ OM.setSymbolicName (getMangledRootDefName (DstI.Operands [OpIdx].Name ));
2111+ M.defineOperand (OM.getSymbolicName (), OM);
2112+ } else {
2113+ M.definePhysRegOperand (DstPhysDefs[OpIdx - DstNumVirtDefs], OM);
2114+ }
21052115 if (MatchedRC.is <const Record *>())
21062116 MatchedRC = &Target.getRegisterClass (MatchedRC.get <const Record *>());
21072117 OM.addPredicate <RegisterBankOperandMatcher>(
@@ -2110,16 +2120,11 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
21102120 }
21112121
21122122 auto DstMIBuilderOrError =
2113- createAndImportInstructionRenderer (M, InsnMatcher, Src, Dst);
2123+ createAndImportInstructionRenderer (M, InsnMatcher, Src, Dst, DstPhysDefs );
21142124 if (auto Error = DstMIBuilderOrError.takeError ())
21152125 return std::move (Error);
21162126 BuildMIAction &DstMIBuilder = DstMIBuilderOrError.get ();
21172127
2118- // Render the implicit defs.
2119- // These are only added to the root of the result.
2120- if (auto Error = importImplicitDefRenderers (DstMIBuilder, P.getDstRegs ()))
2121- return std::move (Error);
2122-
21232128 DstMIBuilder.chooseInsnToMutate (M);
21242129
21252130 // Constrain the registers to classes. This is normally derived from the
0 commit comments