diff options
Diffstat (limited to 'llvm/utils/TableGen/GlobalISelEmitter.cpp')
-rw-r--r-- | llvm/utils/TableGen/GlobalISelEmitter.cpp | 83 |
1 files changed, 65 insertions, 18 deletions
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 7a500eaf411..34920ce02e2 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -135,6 +135,9 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) { std::string Explanation = ""; std::string Separator = ""; if (N->isLeaf()) { + if (IntInit *Int = dyn_cast<IntInit>(N->getLeafValue())) + return Error::success(); + Explanation = "Is a leaf"; Separator = ", "; } @@ -272,6 +275,7 @@ public: OPM_ComplexPattern, OPM_Instruction, OPM_Int, + OPM_LiteralInt, OPM_LLT, OPM_RegBank, OPM_MBB, @@ -406,13 +410,14 @@ public: } }; -/// Generates code to check that an operand is a particular int. -class IntOperandMatcher : public OperandPredicateMatcher { +/// Generates code to check that an operand is a G_CONSTANT with a particular +/// int. +class ConstantIntOperandMatcher : public OperandPredicateMatcher { protected: int64_t Value; public: - IntOperandMatcher(int64_t Value) + ConstantIntOperandMatcher(int64_t Value) : OperandPredicateMatcher(OPM_Int), Value(Value) {} static bool classof(const OperandPredicateMatcher *P) { @@ -425,6 +430,27 @@ public: } }; +/// Generates code to check that an operand is a raw int (where MO.isImm() or +/// MO.isCImm() is true). +class LiteralIntOperandMatcher : public OperandPredicateMatcher { +protected: + int64_t Value; + +public: + LiteralIntOperandMatcher(int64_t Value) + : OperandPredicateMatcher(OPM_LiteralInt), Value(Value) {} + + static bool classof(const OperandPredicateMatcher *P) { + return P->getKind() == OPM_LiteralInt; + } + + void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule, + StringRef OperandExpr) const override { + OS << OperandExpr << ".isCImm() && " << OperandExpr + << ".getCImm()->equalsInt(" << Value << ")"; + } +}; + /// Generates code to check that a set of predicates match for a particular /// operand. class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> { @@ -1236,7 +1262,7 @@ private: createAndImportSelDAGMatcher(InstructionMatcher &InsnMatcher, const TreePatternNode *Src) const; Error importChildMatcher(InstructionMatcher &InsnMatcher, - TreePatternNode *SrcChild, unsigned OpIdx, + const TreePatternNode *SrcChild, unsigned OpIdx, unsigned &TempOpIdx) const; Expected<BuildMIAction &> createAndImportInstructionRenderer( RuleMatcher &M, const TreePatternNode *Dst, @@ -1299,14 +1325,23 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher( if (Src->getExtTypes().size() > 1) return failedImport("Src pattern has multiple results"); - auto SrcGIOrNull = findNodeEquiv(Src->getOperator()); - if (!SrcGIOrNull) - return failedImport("Pattern operator lacks an equivalent Instruction" + - explainOperator(Src->getOperator())); - auto &SrcGI = *SrcGIOrNull; + if (Src->isLeaf()) { + Init *SrcInit = Src->getLeafValue(); + if (IntInit *SrcIntInit = dyn_cast<IntInit>(SrcInit)) { + InsnMatcher.addPredicate<InstructionOpcodeMatcher>( + &Target.getInstruction(RK.getDef("G_CONSTANT"))); + } else + return failedImport("Unable to deduce gMIR opcode to handle Src (which is a leaf)"); + } else { + auto SrcGIOrNull = findNodeEquiv(Src->getOperator()); + if (!SrcGIOrNull) + return failedImport("Pattern operator lacks an equivalent Instruction" + + explainOperator(Src->getOperator())); + auto &SrcGI = *SrcGIOrNull; - // The operators look good: match the opcode and mutate it to the new one. - InsnMatcher.addPredicate<InstructionOpcodeMatcher>(&SrcGI); + // The operators look good: match the opcode + InsnMatcher.addPredicate<InstructionOpcodeMatcher>(&SrcGI); + } unsigned OpIdx = 0; unsigned TempOpIdx = 0; @@ -1323,18 +1358,27 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher( OM.addPredicate<LLTOperandMatcher>(*OpTyOrNone); } - // Match the used operands (i.e. the children of the operator). - for (unsigned i = 0, e = Src->getNumChildren(); i != e; ++i) { - if (auto Error = importChildMatcher(InsnMatcher, Src->getChild(i), OpIdx++, - TempOpIdx)) - return std::move(Error); + if (Src->isLeaf()) { + Init *SrcInit = Src->getLeafValue(); + if (IntInit *SrcIntInit = dyn_cast<IntInit>(SrcInit)) { + OperandMatcher &OM = InsnMatcher.addOperand(OpIdx++, "", TempOpIdx); + OM.addPredicate<LiteralIntOperandMatcher>(SrcIntInit->getValue()); + } else + return failedImport("Unable to deduce gMIR opcode to handle Src (which is a leaf)"); + } else { + // Match the used operands (i.e. the children of the operator). + for (unsigned i = 0, e = Src->getNumChildren(); i != e; ++i) { + if (auto Error = importChildMatcher(InsnMatcher, Src->getChild(i), + OpIdx++, TempOpIdx)) + return std::move(Error); + } } return InsnMatcher; } Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher, - TreePatternNode *SrcChild, + const TreePatternNode *SrcChild, unsigned OpIdx, unsigned &TempOpIdx) const { OperandMatcher &OM = @@ -1379,7 +1423,7 @@ Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher, // Check for constant immediates. if (auto *ChildInt = dyn_cast<IntInit>(SrcChild->getLeafValue())) { - OM.addPredicate<IntOperandMatcher>(ChildInt->getValue()); + OM.addPredicate<ConstantIntOperandMatcher>(ChildInt->getValue()); return Error::success(); } @@ -1605,6 +1649,9 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { return failedImport("Src pattern root isn't a trivial operator (" + toString(std::move(Err)) + ")"); + if (Dst->isLeaf()) + return failedImport("Dst pattern root isn't a known leaf"); + // Start with the defined operands (i.e., the results of the root operator). Record *DstOp = Dst->getOperator(); if (!DstOp->isSubClassOf("Instruction")) |