@@ -404,10 +404,11 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
404404 createInstructionRenderer (action_iterator InsertPt, RuleMatcher &M,
405405 const TreePatternNode &Dst);
406406
407- Expected<action_iterator>
408- importExplicitDefRenderers (action_iterator InsertPt, RuleMatcher &M,
409- BuildMIAction &DstMIBuilder,
410- const TreePatternNode &Dst, unsigned Start = 0 );
407+ Expected<action_iterator> importDefRenderers (action_iterator InsertPt,
408+ RuleMatcher &M,
409+ BuildMIAction &DstMIBuilder,
410+ const TreePatternNode &Dst,
411+ bool IsRoot);
411412
412413 Expected<action_iterator>
413414 importExplicitUseRenderers (action_iterator InsertPt, RuleMatcher &M,
@@ -420,8 +421,6 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
420421 Error importDefaultOperandRenderers (action_iterator InsertPt, RuleMatcher &M,
421422 BuildMIAction &DstMIBuilder,
422423 const DAGDefaultOperand &DefaultOp) const ;
423- Error importImplicitDefRenderers (BuildMIAction &DstMIBuilder,
424- ArrayRef<const Record *> ImplicitDefs) const ;
425424
426425 // / Analyze pattern \p P, returning a matcher for it if possible.
427426 // / Otherwise, return an Error explaining why we don't support it.
@@ -1379,8 +1378,9 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
13791378 CopyToPhysRegMIBuilder.addRenderer <CopyPhysRegRenderer>(PhysInput.first );
13801379 }
13811380
1382- if (auto Error = importExplicitDefRenderers (InsertPt, M, DstMIBuilder, Dst)
1383- .takeError ())
1381+ if (auto Error =
1382+ importDefRenderers (InsertPt, M, DstMIBuilder, Dst, /* IsRoot=*/ true )
1383+ .takeError ())
13841384 return std::move (Error);
13851385
13861386 if (auto Error = importExplicitUseRenderers (InsertPt, M, DstMIBuilder, Dst)
@@ -1408,8 +1408,8 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
14081408 DstMIBuilder.addRenderer <TempRegRenderer>(TempRegID, true );
14091409
14101410 // Handle additional (ignored) results.
1411- InsertPtOrError = importExplicitDefRenderers (std::prev (*InsertPtOrError), M,
1412- DstMIBuilder, Dst, /* Start =*/ 1 );
1411+ InsertPtOrError = importDefRenderers (std::prev (*InsertPtOrError), M,
1412+ DstMIBuilder, Dst, /* IsRoot =*/ false );
14131413 if (auto Error = InsertPtOrError.takeError ())
14141414 return std::move (Error);
14151415
@@ -1446,13 +1446,14 @@ Expected<action_iterator> GlobalISelEmitter::createInstructionRenderer(
14461446 DstI);
14471447}
14481448
1449- Expected<action_iterator> GlobalISelEmitter::importExplicitDefRenderers (
1450- action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
1451- const TreePatternNode &Dst, unsigned Start) {
1449+ Expected<action_iterator>
1450+ GlobalISelEmitter::importDefRenderers (action_iterator InsertPt, RuleMatcher &M,
1451+ BuildMIAction &DstMIBuilder,
1452+ const TreePatternNode &Dst, bool IsRoot) {
14521453 const CodeGenInstruction *DstI = DstMIBuilder.getCGI ();
14531454
14541455 // Process explicit defs. The caller may have already handled the first def.
1455- for (unsigned I = Start , E = DstI->Operands .NumDefs ; I != E; ++I) {
1456+ for (unsigned I = IsRoot ? 0 : 1 , E = DstI->Operands .NumDefs ; I != E; ++I) {
14561457 const CGIOperandList::OperandInfo &OpInfo = DstI->Operands [I];
14571458 std::string OpName = getMangledRootDefName (OpInfo.Name );
14581459
@@ -1504,11 +1505,21 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitDefRenderers(
15041505 TempRegID, /* IsDef=*/ true , /* SubReg=*/ nullptr , /* IsDead=*/ true );
15051506 }
15061507
1507- // Implicit defs are not currently supported, mark all of them as dead .
1508+ // Process implicit defs .
15081509 for (const Record *Reg : DstI->ImplicitDefs ) {
15091510 std::string OpName = getMangledRootDefName (Reg->getName ());
1510- assert (!M.hasOperand (OpName) && " The pattern should've been rejected" );
1511- DstMIBuilder.setDeadImplicitDef (Reg);
1511+
1512+ if (!IsRoot || !M.hasOperand (OpName)) {
1513+ DstMIBuilder.setDeadImplicitDef (Reg);
1514+ continue ;
1515+ }
1516+
1517+ BuildMIAction &CopyBuilder = M.addAction <BuildMIAction>(
1518+ M.allocateOutputInsnID (), &Target.getInstruction (RK.getDef (" COPY" )));
1519+
1520+ StringRef PermanentRef = M.getOperandMatcher (OpName).getSymbolicName ();
1521+ CopyBuilder.addRenderer <CopyRenderer>(PermanentRef);
1522+ CopyBuilder.addRenderer <AddRegisterRenderer>(Target, Reg);
15121523 }
15131524
15141525 return InsertPt;
@@ -1731,13 +1742,6 @@ Error GlobalISelEmitter::importDefaultOperandRenderers(
17311742 return Error::success ();
17321743}
17331744
1734- Error GlobalISelEmitter::importImplicitDefRenderers (
1735- BuildMIAction &DstMIBuilder, ArrayRef<const Record *> ImplicitDefs) const {
1736- if (!ImplicitDefs.empty ())
1737- return failedImport (" Pattern defines a physical register" );
1738- return Error::success ();
1739- }
1740-
17411745Error GlobalISelEmitter::constrainOperands (action_iterator InsertPt,
17421746 RuleMatcher &M, unsigned InsnID,
17431747 const TreePatternNode &Dst) {
@@ -2114,13 +2118,14 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
21142118 unsigned DstExpDefs = DstI.Operands .NumDefs ,
21152119 DstNumDefs = DstI.ImplicitDefs .size () + DstExpDefs,
21162120 SrcNumDefs = Src.getExtTypes ().size ();
2121+
2122+ bool FoundNoUsePred = false ;
21172123 if (DstNumDefs < SrcNumDefs) {
21182124 if (DstNumDefs != 0 )
21192125 return failedImport (" Src pattern result has more defs than dst MI (" +
21202126 to_string (SrcNumDefs) + " def(s) vs " +
21212127 to_string (DstNumDefs) + " def(s))" );
21222128
2123- bool FoundNoUsePred = false ;
21242129 for (const auto &Pred : InsnMatcher.predicates ()) {
21252130 if ((FoundNoUsePred = isa<NoUsePredicateMatcher>(Pred.get ())))
21262131 break ;
@@ -2133,15 +2138,24 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
21332138
21342139 // The root of the match also has constraints on the register bank so that it
21352140 // matches the result instruction.
2136- unsigned N = std::min (DstExpDefs, SrcNumDefs);
2137- for ( unsigned I = 0 ; I < N; ++I) {
2138- const auto &DstIOperand = DstI. Operands [I] ;
2141+ for ( unsigned I = 0 ; I < SrcNumDefs; ++I) {
2142+ if (FoundNoUsePred)
2143+ continue ;
21392144
21402145 OperandMatcher &OM = InsnMatcher.getOperand (I);
2146+
2147+ if (I >= DstExpDefs) {
2148+ const Record *Reg = DstI.ImplicitDefs [I - DstExpDefs];
2149+ OM.setSymbolicName (getMangledRootDefName (Reg->getName ()));
2150+ M.defineOperand (OM.getSymbolicName (), OM);
2151+ continue ;
2152+ }
2153+
21412154 // The operand names declared in the DstI instruction are unrelated to
21422155 // those used in pattern's source and destination DAGs, so mangle the
21432156 // former to prevent implicitly adding unexpected
21442157 // GIM_CheckIsSameOperand predicates by the defineOperand method.
2158+ const CGIOperandList::OperandInfo &DstIOperand = DstI.Operands [I];
21452159 OM.setSymbolicName (getMangledRootDefName (DstIOperand.Name ));
21462160 M.defineOperand (OM.getSymbolicName (), OM);
21472161
@@ -2159,11 +2173,6 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
21592173 return std::move (Error);
21602174 BuildMIAction &DstMIBuilder = DstMIBuilderOrError.get ();
21612175
2162- // Render the implicit defs.
2163- // These are only added to the root of the result.
2164- if (auto Error = importImplicitDefRenderers (DstMIBuilder, P.getDstRegs ()))
2165- return std::move (Error);
2166-
21672176 DstMIBuilder.chooseInsnToMutate (M);
21682177
21692178 // Constrain the registers to classes. This is normally derived from the
0 commit comments