diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -2140,7 +2140,7 @@ if (R->getName() == "node" || R->getName() == "srcvalue" || R->getName() == "zero_reg" || R->getName() == "immAllOnesV" || - R->getName() == "immAllZerosV") { + R->getName() == "immAllZerosV" || R->getName() == "undef_tied_input") { // Placeholder. return TypeSetByHwMode(); // Unknown. } diff --git a/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/llvm/utils/TableGen/DAGISelMatcherGen.cpp --- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -691,6 +691,17 @@ return; } + if (Def->getName() == "undef_tied_input") { + std::array ResultVTs = { N->getSimpleType(0) }; + std::array InstOps; + auto IDOperandNo = NextRecordedOperandNo++; + AddMatcher(new EmitNodeMatcher("TargetOpcode::IMPLICIT_DEF", + ResultVTs, InstOps, false, false, false, + false, -1, IDOperandNo)); + ResultOps.push_back(IDOperandNo); + return; + } + // Handle a reference to a register class. This is used // in COPY_TO_SUBREG instructions. if (Def->isSubClassOf("RegisterOperand")) diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -3037,7 +3037,8 @@ importExplicitUseRenderer(action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder, TreePatternNode *DstChild); - Error importDefaultOperandRenderers(BuildMIAction &DstMIBuilder, + Error importDefaultOperandRenderers(action_iterator InsertPt, RuleMatcher &M, + BuildMIAction &DstMIBuilder, DagInit *DefaultOps) const; Error importImplicitDefRenderers(BuildMIAction &DstMIBuilder, @@ -3777,7 +3778,8 @@ // end up with too many rendered operands. if (DstIOperand.Rec->isSubClassOf("OperandWithDefaultOps")) { DagInit *DefaultOps = DstIOperand.Rec->getValueAsDag("DefaultOps"); - if (auto Error = importDefaultOperandRenderers(DstMIBuilder, DefaultOps)) + if (auto Error = importDefaultOperandRenderers( + InsertPt, M, DstMIBuilder, DefaultOps)) return std::move(Error); ++NumDefaultOps; continue; @@ -3802,19 +3804,38 @@ } Error GlobalISelEmitter::importDefaultOperandRenderers( - BuildMIAction &DstMIBuilder, DagInit *DefaultOps) const { + action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder, + DagInit *DefaultOps) const { for (const auto *DefaultOp : DefaultOps->getArgs()) { + Optional OpTyOrNone = None; + // Look through ValueType operators. if (const DagInit *DefaultDagOp = dyn_cast(DefaultOp)) { if (const DefInit *DefaultDagOperator = dyn_cast(DefaultDagOp->getOperator())) { if (DefaultDagOperator->getDef()->isSubClassOf("ValueType")) + OpTyOrNone = MVTToLLT(getValueType( + DefaultDagOperator->getDef())); DefaultOp = DefaultDagOp->getArg(0); } } if (const DefInit *DefaultDefOp = dyn_cast(DefaultOp)) { - DstMIBuilder.addRenderer(DefaultDefOp->getDef()); + auto Def = DefaultDefOp->getDef(); + if (Def->getName() == "undef_tied_input") { + unsigned TempRegID = M.allocateTempRegID(); + M.insertAction( + InsertPt, OpTyOrNone.getValue(), TempRegID); + InsertPt = M.insertAction( + InsertPt, M.allocateOutputInsnID(), + &Target.getInstruction(RK.getDef("IMPLICIT_DEF"))); + BuildMIAction &IDMIBuilder = *static_cast( + InsertPt->get()); + IDMIBuilder.addRenderer(TempRegID); + DstMIBuilder.addRenderer(TempRegID); + } else { + DstMIBuilder.addRenderer(Def); + } continue; }