@@ -404,9 +404,11 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
404404 createInstructionRenderer (action_iterator InsertPt, RuleMatcher &M,
405405 const TreePatternNode &Dst) const ;
406406
407- Expected<action_iterator> importExplicitDefRenderers (
408- action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
409- const TreePatternNode &Dst, unsigned Start = 0 ) const ;
407+ Expected<action_iterator> importDefRenderers (action_iterator InsertPt,
408+ RuleMatcher &M,
409+ BuildMIAction &DstMIBuilder,
410+ const TreePatternNode &Dst,
411+ bool IsRoot) const ;
410412
411413 Expected<action_iterator>
412414 importExplicitUseRenderers (action_iterator InsertPt, RuleMatcher &M,
@@ -419,8 +421,6 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
419421 Error importDefaultOperandRenderers (action_iterator InsertPt, RuleMatcher &M,
420422 BuildMIAction &DstMIBuilder,
421423 const DAGDefaultOperand &DefaultOp) const ;
422- Error importImplicitDefRenderers (BuildMIAction &DstMIBuilder,
423- ArrayRef<const Record *> ImplicitDefs) const ;
424424
425425 // / Analyze pattern \p P, returning a matcher for it if possible.
426426 // / Otherwise, return an Error explaining why we don't support it.
@@ -1379,8 +1379,9 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
13791379 CopyToPhysRegMIBuilder.addRenderer <CopyPhysRegRenderer>(PhysInput.first );
13801380 }
13811381
1382- if (auto Error = importExplicitDefRenderers (InsertPt, M, DstMIBuilder, Dst)
1383- .takeError ())
1382+ if (auto Error =
1383+ importDefRenderers (InsertPt, M, DstMIBuilder, Dst, /* IsRoot=*/ true )
1384+ .takeError ())
13841385 return std::move (Error);
13851386
13861387 if (auto Error = importExplicitUseRenderers (InsertPt, M, DstMIBuilder, Dst)
@@ -1408,8 +1409,8 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
14081409 DstMIBuilder.addRenderer <TempRegRenderer>(TempRegID, true );
14091410
14101411 // Handle additional (ignored) results.
1411- InsertPtOrError = importExplicitDefRenderers (std::prev (*InsertPtOrError), M,
1412- DstMIBuilder, Dst, /* Start =*/ 1 );
1412+ InsertPtOrError = importDefRenderers (std::prev (*InsertPtOrError), M,
1413+ DstMIBuilder, Dst, /* IsRoot =*/ false );
14131414 if (auto Error = InsertPtOrError.takeError ())
14141415 return std::move (Error);
14151416
@@ -1448,13 +1449,13 @@ GlobalISelEmitter::createInstructionRenderer(action_iterator InsertPt,
14481449 DstI);
14491450}
14501451
1451- Expected<action_iterator> GlobalISelEmitter::importExplicitDefRenderers (
1452+ Expected<action_iterator> GlobalISelEmitter::importDefRenderers (
14521453 action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
1453- const TreePatternNode &Dst, unsigned Start ) const {
1454+ const TreePatternNode &Dst, bool IsRoot ) const {
14541455 const CodeGenInstruction *DstI = DstMIBuilder.getCGI ();
14551456
14561457 // Process explicit defs. The caller may have already handled the first def.
1457- for (unsigned I = Start , E = DstI->Operands .NumDefs ; I != E; ++I) {
1458+ for (unsigned I = IsRoot ? 0 : 1 , E = DstI->Operands .NumDefs ; I != E; ++I) {
14581459 const CGIOperandList::OperandInfo &OpInfo = DstI->Operands [I];
14591460 std::string OpName = getMangledRootDefName (OpInfo.Name );
14601461
@@ -1506,11 +1507,21 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitDefRenderers(
15061507 TempRegID, /* IsDef=*/ true , /* SubReg=*/ nullptr , /* IsDead=*/ true );
15071508 }
15081509
1509- // Implicit defs are not currently supported, mark all of them as dead .
1510+ // Process implicit defs .
15101511 for (const Record *Reg : DstI->ImplicitDefs ) {
15111512 std::string OpName = getMangledRootDefName (Reg->getName ());
1512- assert (!M.hasOperand (OpName) && " The pattern should've been rejected" );
1513- DstMIBuilder.setDeadImplicitDef (Reg);
1513+
1514+ if (!IsRoot || !M.hasOperand (OpName)) {
1515+ DstMIBuilder.setDeadImplicitDef (Reg);
1516+ continue ;
1517+ }
1518+
1519+ BuildMIAction &CopyBuilder = M.addAction <BuildMIAction>(
1520+ M.allocateOutputInsnID (), &Target.getInstruction (RK.getDef (" COPY" )));
1521+
1522+ StringRef PermanentRef = M.getOperandMatcher (OpName).getSymbolicName ();
1523+ CopyBuilder.addRenderer <CopyRenderer>(PermanentRef);
1524+ CopyBuilder.addRenderer <AddRegisterRenderer>(Target, Reg);
15141525 }
15151526
15161527 return InsertPt;
@@ -1733,13 +1744,6 @@ Error GlobalISelEmitter::importDefaultOperandRenderers(
17331744 return Error::success ();
17341745}
17351746
1736- Error GlobalISelEmitter::importImplicitDefRenderers (
1737- BuildMIAction &DstMIBuilder, ArrayRef<const Record *> ImplicitDefs) const {
1738- if (!ImplicitDefs.empty ())
1739- return failedImport (" Pattern defines a physical register" );
1740- return Error::success ();
1741- }
1742-
17431747Error GlobalISelEmitter::constrainOperands (action_iterator InsertPt,
17441748 RuleMatcher &M, unsigned InsnID,
17451749 const TreePatternNode &Dst) const {
@@ -2116,13 +2120,14 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
21162120 unsigned DstExpDefs = DstI.Operands .NumDefs ,
21172121 DstNumDefs = DstI.ImplicitDefs .size () + DstExpDefs,
21182122 SrcNumDefs = Src.getExtTypes ().size ();
2123+
2124+ bool FoundNoUsePred = false ;
21192125 if (DstNumDefs < SrcNumDefs) {
21202126 if (DstNumDefs != 0 )
21212127 return failedImport (" Src pattern result has more defs than dst MI (" +
21222128 to_string (SrcNumDefs) + " def(s) vs " +
21232129 to_string (DstNumDefs) + " def(s))" );
21242130
2125- bool FoundNoUsePred = false ;
21262131 for (const auto &Pred : InsnMatcher.predicates ()) {
21272132 if ((FoundNoUsePred = isa<NoUsePredicateMatcher>(Pred.get ())))
21282133 break ;
@@ -2135,15 +2140,24 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
21352140
21362141 // The root of the match also has constraints on the register bank so that it
21372142 // matches the result instruction.
2138- unsigned N = std::min (DstExpDefs, SrcNumDefs);
2139- for ( unsigned I = 0 ; I < N; ++I) {
2140- const auto &DstIOperand = DstI. Operands [I] ;
2143+ for ( unsigned I = 0 ; I < SrcNumDefs; ++I) {
2144+ if (FoundNoUsePred)
2145+ continue ;
21412146
21422147 OperandMatcher &OM = InsnMatcher.getOperand (I);
2148+
2149+ if (I >= DstExpDefs) {
2150+ const Record *Reg = DstI.ImplicitDefs [I - DstExpDefs];
2151+ OM.setSymbolicName (getMangledRootDefName (Reg->getName ()));
2152+ M.defineOperand (OM.getSymbolicName (), OM);
2153+ continue ;
2154+ }
2155+
21432156 // The operand names declared in the DstI instruction are unrelated to
21442157 // those used in pattern's source and destination DAGs, so mangle the
21452158 // former to prevent implicitly adding unexpected
21462159 // GIM_CheckIsSameOperand predicates by the defineOperand method.
2160+ const CGIOperandList::OperandInfo &DstIOperand = DstI.Operands [I];
21472161 OM.setSymbolicName (getMangledRootDefName (DstIOperand.Name ));
21482162 M.defineOperand (OM.getSymbolicName (), OM);
21492163
@@ -2161,11 +2175,6 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
21612175 return std::move (Error);
21622176 BuildMIAction &DstMIBuilder = DstMIBuilderOrError.get ();
21632177
2164- // Render the implicit defs.
2165- // These are only added to the root of the result.
2166- if (auto Error = importImplicitDefRenderers (DstMIBuilder, P.getDstRegs ()))
2167- return std::move (Error);
2168-
21692178 DstMIBuilder.chooseInsnToMutate (M);
21702179
21712180 // Constrain the registers to classes. This is normally derived from the
0 commit comments