From de234847e9dbc26d8b3377871fde3943c6fb309f Mon Sep 17 00:00:00 2001 From: Sjoerd Meijer Date: Thu, 30 May 2019 07:30:37 +0000 Subject: [PATCH] [TableGen] New default operand "undef_tied_input" This is a new special identifier which you can use as a default in OperandWithDefaultOps. The idea is that you use it for an input operand of an instruction that's tied to an output operand, and its semantics are that (in the default case) the input operand's value is not used at all. The detailed effect is that when instruction selection emits the instruction in the form of a pre-regalloc MachineInstr, it creates an IMPLICIT_DEF node to use as that input. If you're creating an MCInst with explicit register names, then the right handling would be to set the input operand to the same register as the output one (honouring the tie) and to add the 'undef' flag indicating that that register is deemed to acquire a new don't-care definition just before we read it. But I haven't done that in this commit, because there was no need to - no Tablegen backend seems to autogenerate default fields in an MCInst. Patch by: Simon Tatham Differential Revision: https://reviews.llvm.org/D60696 llvm-svn: 362064 --- llvm/utils/TableGen/CodeGenDAGPatterns.cpp | 2 +- llvm/utils/TableGen/DAGISelMatcherGen.cpp | 11 ++++++++ llvm/utils/TableGen/GlobalISelEmitter.cpp | 29 +++++++++++++++++++--- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index 4b491bf3c924..54f3e006608a 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -2132,7 +2132,7 @@ static TypeSetByHwMode getImplicitType(Record *R, unsigned ResNo, 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 index b2285befad3a..3d3ae9c21ebe 100644 --- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -691,6 +691,17 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, 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 index 839529601b98..ad13b33f8b75 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -3037,7 +3037,8 @@ private: 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 @@ Expected GlobalISelEmitter::importExplicitUseRenderers( // 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 @@ Expected GlobalISelEmitter::importExplicitUseRenderers( } 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; }