diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 |
| commit | 08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (patch) | |
| tree | 80108f0f128657f8623f8f66ad9735b4d88e7b47 /utils/TableGen | |
| parent | 7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (diff) | |
Notes
Diffstat (limited to 'utils/TableGen')
| -rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.cpp | 30 | ||||
| -rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.h | 12 | ||||
| -rw-r--r-- | utils/TableGen/DAGISelMatcherGen.cpp | 6 | ||||
| -rw-r--r-- | utils/TableGen/GlobalISelEmitter.cpp | 120 | ||||
| -rw-r--r-- | utils/TableGen/OptParserEmitter.cpp | 10 |
5 files changed, 127 insertions, 51 deletions
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 7c41d9fad696..03914ef98952 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -2762,8 +2762,8 @@ public: AnalyzeNode(Pat->getTree(0)); } - void Analyze(const PatternToMatch *Pat) { - AnalyzeNode(Pat->getSrcPattern()); + void Analyze(const PatternToMatch &Pat) { + AnalyzeNode(Pat.getSrcPattern()); } private: @@ -3220,7 +3220,7 @@ static void FindNames(const TreePatternNode *P, } void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, - const PatternToMatch &PTM) { + PatternToMatch &&PTM) { // Do some sanity checking on the pattern we're about to match. std::string Reason; if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this)) { @@ -3259,7 +3259,7 @@ void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, SrcNames[Entry.first].second == 1) Pattern->error("Pattern has dead named input: $" + Entry.first); - PatternsToMatch.push_back(PTM); + PatternsToMatch.push_back(std::move(PTM)); } @@ -3289,9 +3289,7 @@ void CodeGenDAGPatterns::InferInstructionFlags() { // Second, look for single-instruction patterns defined outside the // instruction. - for (ptm_iterator I = ptm_begin(), E = ptm_end(); I != E; ++I) { - const PatternToMatch &PTM = *I; - + for (const PatternToMatch &PTM : ptms()) { // We can only infer from single-instruction patterns, otherwise we won't // know which instruction should get the flags. SmallVector<Record*, 8> PatInstrs; @@ -3307,7 +3305,7 @@ void CodeGenDAGPatterns::InferInstructionFlags() { continue; InstAnalyzer PatInfo(*this); - PatInfo.Analyze(&PTM); + PatInfo.Analyze(PTM); Errors += InferFromPattern(InstInfo, PatInfo, PTM.getSrcRecord()); } @@ -3367,7 +3365,7 @@ void CodeGenDAGPatterns::VerifyInstructionFlags() { // Analyze the source pattern. InstAnalyzer PatInfo(*this); - PatInfo.Analyze(&PTM); + PatInfo.Analyze(PTM); // Collect error messages. SmallVector<std::string, 4> Msgs; @@ -3553,14 +3551,12 @@ void CodeGenDAGPatterns::ParsePatterns() { TreePattern Temp(Result.getRecord(), DstPattern, false, *this); Temp.InferAllTypes(); - - AddPatternToMatch(Pattern, - PatternToMatch(CurPattern, - CurPattern->getValueAsListInit("Predicates"), - Pattern->getTree(0), - Temp.getOnlyTree(), InstImpResults, - CurPattern->getValueAsInt("AddedComplexity"), - CurPattern->getID())); + AddPatternToMatch( + Pattern, + PatternToMatch( + CurPattern, CurPattern->getValueAsListInit("Predicates"), + Pattern->getTree(0), Temp.getOnlyTree(), std::move(InstImpResults), + CurPattern->getValueAsInt("AddedComplexity"), CurPattern->getID())); } } diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 5c56fb644e7f..8b3e19142370 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -684,12 +684,12 @@ public: /// processed to produce isel. class PatternToMatch { public: - PatternToMatch(Record *srcrecord, ListInit *preds, - TreePatternNode *src, TreePatternNode *dst, - const std::vector<Record*> &dstregs, + PatternToMatch(Record *srcrecord, ListInit *preds, TreePatternNode *src, + TreePatternNode *dst, std::vector<Record *> dstregs, int complexity, unsigned uid) - : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst), - Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {} + : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), + DstPattern(dst), Dstregs(std::move(dstregs)), + AddedComplexity(complexity), ID(uid) {} Record *SrcRecord; // Originating Record for the pattern. ListInit *Predicates; // Top level predicate conditions to match. @@ -853,7 +853,7 @@ private: void GenerateVariants(); void VerifyInstructionFlags(); - void AddPatternToMatch(TreePattern *Pattern, const PatternToMatch &PTM); + void AddPatternToMatch(TreePattern *Pattern, PatternToMatch &&PTM); void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, std::map<std::string, TreePatternNode*> &InstInputs, diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index aafc1157893e..d239f96d2a60 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -848,8 +848,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other) HandledReg = II.ImplicitDefs[0]; - for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) { - Record *Reg = Pattern.getDstRegs()[i]; + for (Record *Reg : Pattern.getDstRegs()) { if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue; ResultVTs.push_back(getRegisterValueType(Reg, CGT)); } @@ -972,8 +971,7 @@ void MatcherGen::EmitResultCode() { HandledReg = II.ImplicitDefs[0]; } - for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) { - Record *Reg = Pattern.getDstRegs()[i]; + for (Record *Reg : Pattern.getDstRegs()) { if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue; ++NumSrcResults; } diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp index 88ded1f25ffb..03d231a153dc 100644 --- a/utils/TableGen/GlobalISelEmitter.cpp +++ b/utils/TableGen/GlobalISelEmitter.cpp @@ -158,6 +158,16 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) { return failedImport(Explanation); } +static Record *getInitValueAsRegClass(Init *V) { + if (DefInit *VDefInit = dyn_cast<DefInit>(V)) { + if (VDefInit->getDef()->isSubClassOf("RegisterOperand")) + return VDefInit->getDef()->getValueAsDef("RegClass"); + if (VDefInit->getDef()->isSubClassOf("RegisterClass")) + return VDefInit->getDef(); + } + return nullptr; +} + //===- Matchers -----------------------------------------------------------===// class OperandMatcher; @@ -973,6 +983,7 @@ public: /// into the desired instruction when this is possible. class BuildMIAction : public MatchAction { private: + std::string Name; const CodeGenInstruction *I; const InstructionMatcher &Matched; std::vector<std::unique_ptr<OperandRenderer>> OperandRenderers; @@ -996,8 +1007,9 @@ private: } public: - BuildMIAction(const CodeGenInstruction *I, const InstructionMatcher &Matched) - : I(I), Matched(Matched) {} + BuildMIAction(const StringRef Name, const CodeGenInstruction *I, + const InstructionMatcher &Matched) + : Name(Name), I(I), Matched(Matched) {} template <class Kind, class... Args> Kind &addRenderer(Args&&... args) { @@ -1032,7 +1044,7 @@ public: } } - OS << " MachineInstr &NewI = " << RecycleVarName << ";\n"; + OS << " MachineInstr &" << Name << " = " << RecycleVarName << ";\n"; return; } @@ -1050,7 +1062,40 @@ public: OS << " for (const auto &MMO : FromMI->memoperands())\n"; OS << " MIB.addMemOperand(MMO);\n"; OS << " " << RecycleVarName << ".eraseFromParent();\n"; - OS << " MachineInstr &NewI = *MIB;\n"; + OS << " MachineInstr &" << Name << " = *MIB;\n"; + } +}; + +/// Generates code to constrain the operands of an output instruction to the +/// register classes specified by the definition of that instruction. +class ConstrainOperandsToDefinitionAction : public MatchAction { + std::string Name; + +public: + ConstrainOperandsToDefinitionAction(const StringRef Name) : Name(Name) {} + + void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule, + StringRef RecycleVarName) const override { + OS << " constrainSelectedInstRegOperands(" << Name << ", TII, TRI, RBI);\n"; + } +}; + +/// Generates code to constrain the specified operand of an output instruction +/// to the specified register class. +class ConstrainOperandToRegClassAction : public MatchAction { + std::string Name; + unsigned OpIdx; + const CodeGenRegisterClass &RC; + +public: + ConstrainOperandToRegClassAction(const StringRef Name, unsigned OpIdx, + const CodeGenRegisterClass &RC) + : Name(Name), OpIdx(OpIdx), RC(RC) {} + + void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule, + StringRef RecycleVarName) const override { + OS << " constrainOperandRegToRegClass(" << Name << ", " << OpIdx + << ", " << RC.getQualifiedName() << "RegClass, TII, TRI, RBI);\n"; } }; @@ -1205,7 +1250,6 @@ void RuleMatcher::emit(raw_ostream &OS, MA->emitCxxActionStmts(OS, *this, "I"); } - OS << " constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);\n"; OS << " return true;\n"; OS << " }\n"; OS << " return false;\n"; @@ -1439,15 +1483,10 @@ Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher, auto *ChildRec = ChildDefInit->getDef(); // Check for register classes. - if (ChildRec->isSubClassOf("RegisterClass")) { - OM.addPredicate<RegisterBankOperandMatcher>( - Target.getRegisterClass(ChildRec)); - return Error::success(); - } - - if (ChildRec->isSubClassOf("RegisterOperand")) { + if (ChildRec->isSubClassOf("RegisterClass") || + ChildRec->isSubClassOf("RegisterOperand")) { OM.addPredicate<RegisterBankOperandMatcher>( - Target.getRegisterClass(ChildRec->getValueAsDef("RegClass"))); + Target.getRegisterClass(getInitValueAsRegClass(ChildDefInit))); return Error::success(); } @@ -1554,22 +1593,33 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer( "Pattern operator isn't an instruction (it's a ValueType)"); return failedImport("Pattern operator isn't an instruction"); } - auto &DstI = Target.getInstruction(DstOp); + CodeGenInstruction *DstI = &Target.getInstruction(DstOp); + + unsigned DstINumUses = DstI->Operands.size() - DstI->Operands.NumDefs; + unsigned ExpectedDstINumUses = Dst->getNumChildren(); - auto &DstMIBuilder = M.addAction<BuildMIAction>(&DstI, InsnMatcher); + // COPY_TO_REGCLASS is just a copy with a ConstrainOperandToRegClassAction + // attached. + if (DstI->TheDef->getName() == "COPY_TO_REGCLASS") { + DstI = &Target.getInstruction(RK.getDef("COPY")); + DstINumUses--; // Ignore the class constraint. + ExpectedDstINumUses--; + } + + auto &DstMIBuilder = M.addAction<BuildMIAction>("NewI", DstI, InsnMatcher); // Render the explicit defs. - for (unsigned I = 0; I < DstI.Operands.NumDefs; ++I) { - const auto &DstIOperand = DstI.Operands[I]; + for (unsigned I = 0; I < DstI->Operands.NumDefs; ++I) { + const CGIOperandList::OperandInfo &DstIOperand = DstI->Operands[I]; DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstIOperand.Name); } // Render the explicit uses. unsigned Child = 0; - unsigned DstINumUses = DstI.Operands.size() - DstI.Operands.NumDefs; unsigned NumDefaultOps = 0; for (unsigned I = 0; I != DstINumUses; ++I) { - const auto &DstIOperand = DstI.Operands[DstI.Operands.NumDefs + I]; + const CGIOperandList::OperandInfo &DstIOperand = + DstI->Operands[DstI->Operands.NumDefs + I]; // If the operand has default values, introduce them now. // FIXME: Until we have a decent test case that dictates we should do @@ -1590,10 +1640,10 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer( ++Child; } - if (NumDefaultOps + Dst->getNumChildren() != DstINumUses) + if (NumDefaultOps + ExpectedDstINumUses != DstINumUses) return failedImport("Expected " + llvm::to_string(DstINumUses) + " used operands but found " + - llvm::to_string(Dst->getNumChildren()) + + llvm::to_string(ExpectedDstINumUses) + " explicit ones and " + llvm::to_string(NumDefaultOps) + " default ones"); @@ -1684,10 +1734,16 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { const auto &DstIOperand = DstI.Operands[OpIdx]; Record *DstIOpRec = DstIOperand.Rec; - if (DstIOpRec->isSubClassOf("RegisterOperand")) + if (DstI.TheDef->getName() == "COPY_TO_REGCLASS") { + DstIOpRec = getInitValueAsRegClass(Dst->getChild(1)->getLeafValue()); + + if (DstIOpRec == nullptr) + return failedImport( + "COPY_TO_REGCLASS operand #1 isn't a register class"); + } else if (DstIOpRec->isSubClassOf("RegisterOperand")) DstIOpRec = DstIOpRec->getValueAsDef("RegClass"); - if (!DstIOpRec->isSubClassOf("RegisterClass")) - return failedImport("Dst MI def isn't a register class"); + else if (!DstIOpRec->isSubClassOf("RegisterClass")) + return failedImport("Dst MI def isn't a register class" + to_string(*Dst)); OperandMatcher &OM = InsnMatcher.getOperand(OpIdx); OM.setSymbolicName(DstIOperand.Name); @@ -1707,6 +1763,22 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { if (auto Error = importImplicitDefRenderers(DstMIBuilder, P.getDstRegs())) return std::move(Error); + // Constrain the registers to classes. This is normally derived from the + // emitted instruction but a few instructions require special handling. + if (DstI.TheDef->getName() == "COPY_TO_REGCLASS") { + // COPY_TO_REGCLASS does not provide operand constraints itself but the + // result is constrained to the class given by the second child. + Record *DstIOpRec = + getInitValueAsRegClass(Dst->getChild(1)->getLeafValue()); + + if (DstIOpRec == nullptr) + return failedImport("COPY_TO_REGCLASS operand #1 isn't a register class"); + + M.addAction<ConstrainOperandToRegClassAction>( + "NewI", 0, Target.getRegisterClass(DstIOpRec)); + } else + M.addAction<ConstrainOperandsToDefinitionAction>("NewI"); + // We're done with this pattern! It's eligible for GISel emission; return it. ++NumPatternImported; return std::move(M); diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index 04e6537f3d15..e3777d036a23 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -196,6 +196,9 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << ", nullptr"; // The option meta-variable name (unused). + OS << ", nullptr"; + + // The option Values (unused for groups). OS << ", nullptr)\n"; } OS << "\n"; @@ -285,6 +288,13 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { else OS << "nullptr"; + // The option Values. Used for shell autocompletion. + OS << ", "; + if (!isa<UnsetInit>(R.getValueInit("Values"))) + write_cstring(OS, R.getValueAsString("Values")); + else + OS << "nullptr"; + OS << ")\n"; } OS << "#endif // OPTION\n"; |
