@@ -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.
@@ -1375,8 +1374,9 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
13751374 CopyToPhysRegMIBuilder.addRenderer <CopyPhysRegRenderer>(PhysInput.first );
13761375 }
13771376
1378- if (auto Error = importExplicitDefRenderers (InsertPt, M, DstMIBuilder, Dst)
1379- .takeError ())
1377+ if (auto Error =
1378+ importDefRenderers (InsertPt, M, DstMIBuilder, Dst, /* IsRoot=*/ true )
1379+ .takeError ())
13801380 return std::move (Error);
13811381
13821382 if (auto Error = importExplicitUseRenderers (InsertPt, M, DstMIBuilder, Dst)
@@ -1404,8 +1404,8 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
14041404 DstMIBuilder.addRenderer <TempRegRenderer>(TempRegID, true );
14051405
14061406 // Handle additional (ignored) results.
1407- InsertPtOrError = importExplicitDefRenderers (std::prev (*InsertPtOrError), M,
1408- DstMIBuilder, Dst, /* Start =*/ 1 );
1407+ InsertPtOrError = importDefRenderers (std::prev (*InsertPtOrError), M,
1408+ DstMIBuilder, Dst, /* IsRoot =*/ false );
14091409 if (auto Error = InsertPtOrError.takeError ())
14101410 return std::move (Error);
14111411
@@ -1442,19 +1442,15 @@ Expected<action_iterator> GlobalISelEmitter::createInstructionRenderer(
14421442 DstI);
14431443}
14441444
1445- Expected<action_iterator> GlobalISelEmitter::importExplicitDefRenderers (
1445+ Expected<action_iterator> GlobalISelEmitter::importDefRenderers (
14461446 action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
1447- const TreePatternNode &Dst, unsigned Start ) {
1447+ const TreePatternNode &Dst, bool IsRoot ) {
14481448 const CodeGenInstruction *DstI = DstMIBuilder.getCGI ();
14491449
1450- // Some instructions have multiple defs, but are missing a type entry
1451- // (e.g. s_cc_out operands).
1452- if (Dst.getExtTypes ().size () < DstI->Operands .NumDefs )
1453- return failedImport (" unhandled discarded def" );
1454-
14551450 // Process explicit defs. The caller may have already handled the first def.
1456- for (unsigned I = Start, E = DstI->Operands .NumDefs ; I != E; ++I) {
1457- std::string OpName = getMangledRootDefName (DstI->Operands [I].Name );
1451+ for (unsigned I = IsRoot ? 0 : 1 , E = DstI->Operands .NumDefs ; I != E; ++I) {
1452+ const CGIOperandList::OperandInfo &OpInfo = DstI->Operands [I];
1453+ std::string OpName = getMangledRootDefName (OpInfo.Name );
14581454
14591455 // If the def is used in the source DAG, forward it.
14601456 if (M.hasOperand (OpName)) {
@@ -1465,6 +1461,19 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitDefRenderers(
14651461 continue ;
14661462 }
14671463
1464+ if (OpInfo.Rec ->isSubClassOf (" OptionalDefOperand" )) {
1465+ const DAGDefaultOperand &ComplexOp = CGP.getDefaultOperand (OpInfo.Rec );
1466+ for (const TreePatternNode &SubOp :
1467+ make_pointee_range (ComplexOp.DefaultOps )) {
1468+ const Record *Reg = cast<DefInit>(SubOp.getLeafValue ())->getDef ();
1469+ assert (Reg->isSubClassOf (" Register" ) &&
1470+ " Optional def can only be a register" );
1471+ DstMIBuilder.addRenderer <AddRegisterRenderer>(
1472+ Target, Reg, /* IsDef=*/ true , /* IsDead=*/ true );
1473+ }
1474+ continue ;
1475+ }
1476+
14681477 // The def is discarded, create a dead virtual register for it.
14691478 const TypeSetByHwMode &ExtTy = Dst.getExtType (I);
14701479 if (!ExtTy.isMachineValueType ())
@@ -1484,8 +1493,23 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitDefRenderers(
14841493 // Implicit defs are not currently supported, mark all of them as dead.
14851494 for (const Record *Reg : DstI->ImplicitDefs ) {
14861495 std::string OpName = getMangledRootDefName (Reg->getName ());
1487- assert (!M.hasOperand (OpName) && " The pattern should've been rejected" );
1488- DstMIBuilder.setDeadImplicitDef (Reg);
1496+
1497+ if (!IsRoot || !M.hasOperand (OpName)) {
1498+ DstMIBuilder.setDeadImplicitDef (Reg);
1499+ continue ;
1500+ }
1501+
1502+ BuildMIAction &CopyBuilder = M.addAction <BuildMIAction>(
1503+ M.allocateOutputInsnID (), &Target.getInstruction (RK.getDef (" COPY" )));
1504+
1505+ StringRef PermanentRef = M.getOperandMatcher (OpName).getSymbolicName ();
1506+ CopyBuilder.addRenderer <CopyRenderer>(PermanentRef);
1507+ CopyBuilder.addRenderer <AddRegisterRenderer>(Target, Reg);
1508+
1509+ const CodeGenRegisterClass *RC = CGRegs.getRegClassForRegister (Reg);
1510+ assert (RC);
1511+ M.addAction <ConstrainOperandToRegClassAction>(CopyBuilder.getInsnID (),
1512+ /* OpIdx=*/ 0 , *RC);
14891513 }
14901514
14911515 return InsertPt;
@@ -1708,13 +1732,6 @@ Error GlobalISelEmitter::importDefaultOperandRenderers(
17081732 return Error::success ();
17091733}
17101734
1711- Error GlobalISelEmitter::importImplicitDefRenderers (
1712- BuildMIAction &DstMIBuilder, ArrayRef<const Record *> ImplicitDefs) const {
1713- if (!ImplicitDefs.empty ())
1714- return failedImport (" Pattern defines a physical register" );
1715- return Error::success ();
1716- }
1717-
17181735Error GlobalISelEmitter::constrainOperands (action_iterator InsertPt,
17191736 RuleMatcher &M, unsigned InsnID,
17201737 const TreePatternNode &Dst) {
@@ -2091,13 +2108,14 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
20912108 unsigned DstExpDefs = DstI.Operands .NumDefs ,
20922109 DstNumDefs = DstI.ImplicitDefs .size () + DstExpDefs,
20932110 SrcNumDefs = Src.getExtTypes ().size ();
2111+
2112+ bool FoundNoUsePred = false ;
20942113 if (DstNumDefs < SrcNumDefs) {
20952114 if (DstNumDefs != 0 )
20962115 return failedImport (" Src pattern result has more defs than dst MI (" +
20972116 to_string (SrcNumDefs) + " def(s) vs " +
20982117 to_string (DstNumDefs) + " def(s))" );
20992118
2100- bool FoundNoUsePred = false ;
21012119 for (const auto &Pred : InsnMatcher.predicates ()) {
21022120 if ((FoundNoUsePred = isa<NoUsePredicateMatcher>(Pred.get ())))
21032121 break ;
@@ -2110,15 +2128,24 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
21102128
21112129 // The root of the match also has constraints on the register bank so that it
21122130 // matches the result instruction.
2113- unsigned N = std::min (DstExpDefs, SrcNumDefs);
2114- for ( unsigned I = 0 ; I < N; ++I) {
2115- const auto &DstIOperand = DstI. Operands [I] ;
2131+ for ( unsigned I = 0 ; I < SrcNumDefs; ++I) {
2132+ if (FoundNoUsePred)
2133+ continue ;
21162134
21172135 OperandMatcher &OM = InsnMatcher.getOperand (I);
2136+
2137+ if (I >= DstExpDefs) {
2138+ const Record *Reg = DstI.ImplicitDefs [I - DstExpDefs];
2139+ OM.setSymbolicName (getMangledRootDefName (Reg->getName ()));
2140+ M.defineOperand (OM.getSymbolicName (), OM);
2141+ continue ;
2142+ }
2143+
21182144 // The operand names declared in the DstI instruction are unrelated to
21192145 // those used in pattern's source and destination DAGs, so mangle the
21202146 // former to prevent implicitly adding unexpected
21212147 // GIM_CheckIsSameOperand predicates by the defineOperand method.
2148+ const CGIOperandList::OperandInfo &DstIOperand = DstI.Operands [I];
21222149 OM.setSymbolicName (getMangledRootDefName (DstIOperand.Name ));
21232150 M.defineOperand (OM.getSymbolicName (), OM);
21242151
@@ -2136,11 +2163,6 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
21362163 return std::move (Error);
21372164 BuildMIAction &DstMIBuilder = DstMIBuilderOrError.get ();
21382165
2139- // Render the implicit defs.
2140- // These are only added to the root of the result.
2141- if (auto Error = importImplicitDefRenderers (DstMIBuilder, P.getDstRegs ()))
2142- return std::move (Error);
2143-
21442166 DstMIBuilder.chooseInsnToMutate (M);
21452167
21462168 // Constrain the registers to classes. This is normally derived from the
0 commit comments