diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/utils/TableGen/GlobalISelEmitter.cpp | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'llvm/utils/TableGen/GlobalISelEmitter.cpp')
-rw-r--r-- | llvm/utils/TableGen/GlobalISelEmitter.cpp | 250 |
1 files changed, 192 insertions, 58 deletions
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index c14294951cc11..4e8dcc52fc202 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -448,7 +448,6 @@ public: : LabelID(LabelID_.hasValue() ? LabelID_.getValue() : ~0u), EmitStr(EmitStr), NumElements(NumElements), Flags(Flags), RawValue(RawValue) { - assert((!LabelID_.hasValue() || LabelID != ~0u) && "This value is reserved for non-labels"); } @@ -1044,6 +1043,28 @@ public: for (const auto &Predicate : predicates()) Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...); } + + /// Provide a function to avoid emitting certain predicates. This is used to + /// defer some predicate checks until after others + using PredicateFilterFunc = std::function<bool(const PredicateTy&)>; + + /// Emit MatchTable opcodes for predicates which satisfy \p + /// ShouldEmitPredicate. This should be called multiple times to ensure all + /// predicates are eventually added to the match table. + template <class... Args> + void emitFilteredPredicateListOpcodes(PredicateFilterFunc ShouldEmitPredicate, + MatchTable &Table, Args &&... args) { + if (Predicates.empty() && !Optimized) { + Table << MatchTable::Comment(getNoPredicateComment()) + << MatchTable::LineBreak; + return; + } + + for (const auto &Predicate : predicates()) { + if (ShouldEmitPredicate(*Predicate)) + Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...); + } + } }; class PredicateMatcher { @@ -1101,6 +1122,13 @@ public: PredicateKind getKind() const { return Kind; } + bool dependsOnOperands() const { + // Custom predicates really depend on the context pattern of the + // instruction, not just the individual instruction. This therefore + // implicitly depends on all other pattern constraints. + return Kind == IPM_GenericPredicate; + } + virtual bool isIdentical(const PredicateMatcher &B) const { return B.getKind() == getKind() && InsnVarID == B.InsnVarID && OpIdx == B.OpIdx; @@ -1498,7 +1526,7 @@ public: const StringRef getSymbolicName() const { return SymbolicName; } void setSymbolicName(StringRef Name) { assert(SymbolicName.empty() && "Operand already has a symbolic name"); - SymbolicName = Name; + SymbolicName = std::string(Name); } /// Construct a new operand predicate and add it to the matcher. @@ -2128,10 +2156,23 @@ public: InstructionNumOperandsMatcher(InsnVarID, getNumOperands()) .emitPredicateOpcodes(Table, Rule); - emitPredicateListOpcodes(Table, Rule); + // First emit all instruction level predicates need to be verified before we + // can verify operands. + emitFilteredPredicateListOpcodes( + [](const PredicateMatcher &P) { + return !P.dependsOnOperands(); + }, Table, Rule); + // Emit all operand constraints. for (const auto &Operand : Operands) Operand->emitPredicateOpcodes(Table, Rule); + + // All of the tablegen defined predicates should now be matched. Now emit + // any custom predicates that rely on all generated checks. + emitFilteredPredicateListOpcodes( + [](const PredicateMatcher &P) { + return P.dependsOnOperands(); + }, Table, Rule); } /// Compare the priority of this object and B. @@ -2585,26 +2626,37 @@ class TempRegRenderer : public OperandRenderer { protected: unsigned InsnID; unsigned TempRegID; + const CodeGenSubRegIndex *SubRegIdx; bool IsDef; public: - TempRegRenderer(unsigned InsnID, unsigned TempRegID, bool IsDef = false) + TempRegRenderer(unsigned InsnID, unsigned TempRegID, bool IsDef = false, + const CodeGenSubRegIndex *SubReg = nullptr) : OperandRenderer(OR_Register), InsnID(InsnID), TempRegID(TempRegID), - IsDef(IsDef) {} + SubRegIdx(SubReg), IsDef(IsDef) {} static bool classof(const OperandRenderer *R) { return R->getKind() == OR_TempRegister; } void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override { - Table << MatchTable::Opcode("GIR_AddTempRegister") - << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID) + if (SubRegIdx) { + assert(!IsDef); + Table << MatchTable::Opcode("GIR_AddTempSubRegister"); + } else + Table << MatchTable::Opcode("GIR_AddTempRegister"); + + Table << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID) << MatchTable::Comment("TempRegID") << MatchTable::IntValue(TempRegID) << MatchTable::Comment("TempRegFlags"); + if (IsDef) Table << MatchTable::NamedValue("RegState::Define"); else Table << MatchTable::IntValue(0); + + if (SubRegIdx) + Table << MatchTable::NamedValue(SubRegIdx->getQualifiedName()); Table << MatchTable::LineBreak; } }; @@ -2779,7 +2831,7 @@ private: std::string S; public: - DebugCommentAction(StringRef S) : S(S) {} + DebugCommentAction(StringRef S) : S(std::string(S)) {} void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override { Table << MatchTable::Comment(S) << MatchTable::LineBreak; @@ -2950,8 +3002,8 @@ public: Table << MatchTable::Opcode("GIR_ConstrainOperandRC") << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID) << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx) - << MatchTable::Comment("RC " + RC.getName()) - << MatchTable::IntValue(RC.EnumValue) << MatchTable::LineBreak; + << MatchTable::NamedValue(RC.getQualifiedName() + "RegClassID") + << MatchTable::LineBreak; } }; @@ -3260,6 +3312,22 @@ void SameOperandMatcher::emitPredicateOpcodes(MatchTable &Table, //===- GlobalISelEmitter class --------------------------------------------===// +static Expected<LLTCodeGen> getInstResultType(const TreePatternNode *Dst) { + ArrayRef<TypeSetByHwMode> ChildTypes = Dst->getExtTypes(); + if (ChildTypes.size() != 1) + return failedImport("Dst pattern child has multiple results"); + + Optional<LLTCodeGen> MaybeOpTy; + if (ChildTypes.front().isMachineValueType()) { + MaybeOpTy = + MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy); + } + + if (!MaybeOpTy) + return failedImport("Dst operand has an unsupported type"); + return *MaybeOpTy; +} + class GlobalISelEmitter { public: explicit GlobalISelEmitter(RecordKeeper &RK); @@ -3269,7 +3337,7 @@ private: const RecordKeeper &RK; const CodeGenDAGPatterns CGP; const CodeGenTarget &Target; - CodeGenRegBank CGRegs; + CodeGenRegBank &CGRegs; /// Keep track of the equivalence between SDNodes and Instruction by mapping /// SDNodes to the GINodeEquiv mapping. We need to map to the GINodeEquiv to @@ -3477,7 +3545,7 @@ GlobalISelEmitter::getEquivNode(Record &Equiv, const TreePatternNode *N) const { GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK) : RK(RK), CGP(RK), Target(CGP.getTargetInfo()), - CGRegs(RK, Target.getHwModes()) {} + CGRegs(Target.getRegBank()) {} //===- Emitter ------------------------------------------------------------===// @@ -3737,7 +3805,7 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher( CCDef->getValueAsString("ICmpPredicate"); if (!PredType.empty()) { - OM.addPredicate<CmpPredicateOperandMatcher>(PredType); + OM.addPredicate<CmpPredicateOperandMatcher>(std::string(PredType)); // Process the other 2 operands normally. --NumChildren; } @@ -3836,9 +3904,10 @@ Error GlobalISelEmitter::importChildMatcher( Record *PhysReg = nullptr; StringRef SrcChildName = getSrcChildName(SrcChild, PhysReg); - OperandMatcher &OM = PhysReg ? - InsnMatcher.addPhysRegInput(PhysReg, OpIdx, TempOpIdx) : - InsnMatcher.addOperand(OpIdx, SrcChildName, TempOpIdx); + OperandMatcher &OM = + PhysReg + ? InsnMatcher.addPhysRegInput(PhysReg, OpIdx, TempOpIdx) + : InsnMatcher.addOperand(OpIdx, std::string(SrcChildName), TempOpIdx); if (OM.isSameAsAnotherOperand()) return Error::success(); @@ -3971,6 +4040,10 @@ Error GlobalISelEmitter::importChildMatcher( "Src pattern child def is an unsupported tablegen class (ImmLeaf)"); } + // Place holder for SRCVALUE nodes. Nothing to do here. + if (ChildRec->getName() == "srcvalue") + return Error::success(); + return failedImport( "Src pattern child def is an unsupported tablegen class"); } @@ -4040,20 +4113,13 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer( } if (DstChild->getOperator()->isSubClassOf("Instruction")) { - ArrayRef<TypeSetByHwMode> ChildTypes = DstChild->getExtTypes(); - if (ChildTypes.size() != 1) - return failedImport("Dst pattern child has multiple results"); - - Optional<LLTCodeGen> OpTyOrNone = None; - if (ChildTypes.front().isMachineValueType()) - OpTyOrNone = - MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy); - if (!OpTyOrNone) - return failedImport("Dst operand has an unsupported type"); + auto OpTy = getInstResultType(DstChild); + if (!OpTy) + return OpTy.takeError(); unsigned TempRegID = Rule.allocateTempRegID(); InsertPt = Rule.insertAction<MakeTempRegisterAction>( - InsertPt, OpTyOrNone.getValue(), TempRegID); + InsertPt, *OpTy, TempRegID); DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID); auto InsertPtOrError = createAndImportSubInstructionRenderer( @@ -4225,7 +4291,7 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer( if (!SubIdx) return failedImport("EXTRACT_SUBREG child #1 is not a subreg index"); - const auto &SrcRCDstRCPair = + const auto SrcRCDstRCPair = (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx); assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass"); M.insertAction<ConstrainOperandToRegClassAction>( @@ -4257,6 +4323,29 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer( return InsertPtOrError.get(); } + if (OpName == "REG_SEQUENCE") { + auto SuperClass = inferRegClassFromPattern(Dst->getChild(0)); + M.insertAction<ConstrainOperandToRegClassAction>( + InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass); + + unsigned Num = Dst->getNumChildren(); + for (unsigned I = 1; I != Num; I += 2) { + TreePatternNode *SubRegChild = Dst->getChild(I + 1); + + auto SubIdx = inferSubRegIndexForNode(SubRegChild); + if (!SubIdx) + return failedImport("REG_SEQUENCE child is not a subreg index"); + + const auto SrcRCDstRCPair = + (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx); + assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass"); + M.insertAction<ConstrainOperandToRegClassAction>( + InsertPt, DstMIBuilder.getInsnID(), I, *SrcRCDstRCPair->second); + } + + return InsertPtOrError.get(); + } + M.insertAction<ConstrainOperandsToDefinitionAction>(InsertPt, DstMIBuilder.getInsnID()); return InsertPtOrError.get(); @@ -4303,33 +4392,51 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers( // EXTRACT_SUBREG needs to use a subregister COPY. if (Name == "EXTRACT_SUBREG") { - if (!Dst->getChild(0)->isLeaf()) - return failedImport("EXTRACT_SUBREG child #1 is not a leaf"); - - if (DefInit *SubRegInit = - dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue())) { - Record *RCDef = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue()); - if (!RCDef) - return failedImport("EXTRACT_SUBREG child #0 could not " - "be coerced to a register class"); - - CodeGenRegisterClass *RC = CGRegs.getRegClass(RCDef); - CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef()); - - const auto &SrcRCDstRCPair = - RC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx); - if (SrcRCDstRCPair.hasValue()) { - assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass"); - if (SrcRCDstRCPair->first != RC) - return failedImport("EXTRACT_SUBREG requires an additional COPY"); - } + DefInit *SubRegInit = dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue()); + if (!SubRegInit) + return failedImport("EXTRACT_SUBREG child #1 is not a subreg index"); + + CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef()); + TreePatternNode *ValChild = Dst->getChild(0); + if (!ValChild->isLeaf()) { + // We really have to handle the source instruction, and then insert a + // copy from the subregister. + auto ExtractSrcTy = getInstResultType(ValChild); + if (!ExtractSrcTy) + return ExtractSrcTy.takeError(); + + unsigned TempRegID = M.allocateTempRegID(); + InsertPt = M.insertAction<MakeTempRegisterAction>( + InsertPt, *ExtractSrcTy, TempRegID); - DstMIBuilder.addRenderer<CopySubRegRenderer>(Dst->getChild(0)->getName(), - SubIdx); + auto InsertPtOrError = createAndImportSubInstructionRenderer( + ++InsertPt, M, ValChild, TempRegID); + if (auto Error = InsertPtOrError.takeError()) + return std::move(Error); + + DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID, false, SubIdx); return InsertPt; } - return failedImport("EXTRACT_SUBREG child #1 is not a subreg index"); + // If this is a source operand, this is just a subregister copy. + Record *RCDef = getInitValueAsRegClass(ValChild->getLeafValue()); + if (!RCDef) + return failedImport("EXTRACT_SUBREG child #0 could not " + "be coerced to a register class"); + + CodeGenRegisterClass *RC = CGRegs.getRegClass(RCDef); + + const auto SrcRCDstRCPair = + RC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx); + if (SrcRCDstRCPair.hasValue()) { + assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass"); + if (SrcRCDstRCPair->first != RC) + return failedImport("EXTRACT_SUBREG requires an additional COPY"); + } + + DstMIBuilder.addRenderer<CopySubRegRenderer>(Dst->getChild(0)->getName(), + SubIdx); + return InsertPt; } if (Name == "REG_SEQUENCE") { @@ -4731,15 +4838,13 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { if (DstIOpRec == nullptr) return failedImport("REG_SEQUENCE operand #0 isn't a register class"); } else if (DstIName == "EXTRACT_SUBREG") { - if (!Dst->getChild(0)->isLeaf()) - return failedImport("EXTRACT_SUBREG operand #0 isn't a leaf"); + auto InferredClass = inferRegClassFromPattern(Dst->getChild(0)); + if (!InferredClass) + return failedImport("Could not infer class for EXTRACT_SUBREG operand #0"); // We can assume that a subregister is in the same bank as it's super // register. - DstIOpRec = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue()); - - if (DstIOpRec == nullptr) - return failedImport("EXTRACT_SUBREG operand #0 isn't a register class"); + DstIOpRec = (*InferredClass)->getDef(); } else if (DstIName == "INSERT_SUBREG") { auto MaybeSuperClass = inferSuperRegisterClassForNode( VTy, Dst->getChild(0), Dst->getChild(2)); @@ -4832,8 +4937,13 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { assert(Src->getExtTypes().size() == 1 && "Expected Src of EXTRACT_SUBREG to have one result type"); - const auto &SrcRCDstRCPair = + const auto SrcRCDstRCPair = (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx); + if (!SrcRCDstRCPair) { + return failedImport("subreg index is incompatible " + "with inferred reg class"); + } + assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass"); M.addAction<ConstrainOperandToRegClassAction>(0, 0, *SrcRCDstRCPair->second); M.addAction<ConstrainOperandToRegClassAction>(0, 1, *SrcRCDstRCPair->first); @@ -4889,6 +4999,30 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { return std::move(M); } + if (DstIName == "REG_SEQUENCE") { + auto SuperClass = inferRegClassFromPattern(Dst->getChild(0)); + + M.addAction<ConstrainOperandToRegClassAction>(0, 0, **SuperClass); + + unsigned Num = Dst->getNumChildren(); + for (unsigned I = 1; I != Num; I += 2) { + TreePatternNode *SubRegChild = Dst->getChild(I + 1); + + auto SubIdx = inferSubRegIndexForNode(SubRegChild); + if (!SubIdx) + return failedImport("REG_SEQUENCE child is not a subreg index"); + + const auto SrcRCDstRCPair = + (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx); + + M.addAction<ConstrainOperandToRegClassAction>(0, I, + *SrcRCDstRCPair->second); + } + + ++NumPatternImported; + return std::move(M); + } + M.addAction<ConstrainOperandsToDefinitionAction>(0); // We're done with this pattern! It's eligible for GISel emission; return it. |