[globalisel][tablegen] Report more detail in some SelectionDAG import failures. NFC

Reviewers: ab, t.p.northover, qcolombet, aditya_nandakumar, rovka

Reviewed By: ab

Subscribers: dberris, kristof.beyls, igorb, llvm-commits

Differential Revision: https://reviews.llvm.org/D31325

llvm-svn: 300186
This commit is contained in:
Daniel Sanders 2017-04-13 09:45:37 +00:00
parent 2d33869806
commit d0656a3af1
1 changed files with 98 additions and 19 deletions

View File

@ -147,8 +147,71 @@ static Optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT) {
return None; return None;
} }
static bool isTrivialOperatorNode(const TreePatternNode *N) { static std::string explainPredicates(const TreePatternNode *N) {
return !N->isLeaf() && !N->hasAnyPredicate() && !N->getTransformFn(); std::string Explanation = "";
StringRef Separator = "";
for (const auto &P : N->getPredicateFns()) {
Explanation +=
(Separator + P.getOrigPatFragRecord()->getRecord()->getName()).str();
if (P.isAlwaysTrue())
Explanation += " always-true";
if (P.isImmediatePattern())
Explanation += " immediate";
}
return Explanation;
}
static std::string explainRulePredicates(const ArrayRef<Init *> Predicates) {
std::string Explanation = "";
StringRef Separator = "";
for (const auto *P : Predicates) {
Explanation += Separator;
if (const DefInit *PDef = dyn_cast<DefInit>(P)) {
Explanation += PDef->getDef()->getName();
} else
Explanation += "<unknown>";
}
return Explanation;
}
std::string explainOperator(Record *Operator) {
if (Operator->isSubClassOf("SDNode"))
return " (" + Operator->getValueAsString("Opcode") + ")";
if (Operator->isSubClassOf("Intrinsic"))
return (" (Operator is an Intrinsic, " + Operator->getName() + ")").str();
return " (Operator not understood)";
}
/// Helper function to let the emitter report skip reason error messages.
static Error failedImport(const Twine &Reason) {
return make_error<StringError>(Reason, inconvertibleErrorCode());
}
static Error isTrivialOperatorNode(const TreePatternNode *N) {
std::string Explanation = "";
std::string Separator = "";
if (N->isLeaf()) {
Explanation = "Is a leaf";
Separator = ", ";
}
if (N->hasAnyPredicate()) {
Explanation = Separator + "Has a predicate (" + explainPredicates(N) + ")";
Separator = ", ";
}
if (N->getTransformFn()) {
Explanation += Separator + "Has a transform function";
Separator = ", ";
}
if (!N->isLeaf() && !N->hasAnyPredicate() && !N->getTransformFn())
return Error::success();
return failedImport(Explanation);
} }
//===- Matchers -----------------------------------------------------------===// //===- Matchers -----------------------------------------------------------===//
@ -1250,16 +1313,12 @@ GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)
//===- Emitter ------------------------------------------------------------===// //===- Emitter ------------------------------------------------------------===//
/// Helper function to let the emitter report skip reason error messages.
static Error failedImport(const Twine &Reason) {
return make_error<StringError>(Reason, inconvertibleErrorCode());
}
Error Error
GlobalISelEmitter::importRulePredicates(RuleMatcher &M, GlobalISelEmitter::importRulePredicates(RuleMatcher &M,
ArrayRef<Init *> Predicates) const { ArrayRef<Init *> Predicates) const {
if (!Predicates.empty()) if (!Predicates.empty())
return failedImport("Pattern has a predicate"); return failedImport("Pattern has a rule predicate (" +
explainRulePredicates(Predicates) + ")");
return Error::success(); return Error::success();
} }
@ -1271,7 +1330,8 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
auto SrcGIOrNull = findNodeEquiv(Src->getOperator()); auto SrcGIOrNull = findNodeEquiv(Src->getOperator());
if (!SrcGIOrNull) if (!SrcGIOrNull)
return failedImport("Pattern operator lacks an equivalent Instruction"); return failedImport("Pattern operator lacks an equivalent Instruction" +
explainOperator(Src->getOperator()));
auto &SrcGI = *SrcGIOrNull; auto &SrcGI = *SrcGIOrNull;
// The operators look good: match the opcode and mutate it to the new one. // The operators look good: match the opcode and mutate it to the new one.
@ -1310,7 +1370,8 @@ Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher,
InsnMatcher.addOperand(OpIdx, SrcChild->getName(), TempOpIdx); InsnMatcher.addOperand(OpIdx, SrcChild->getName(), TempOpIdx);
if (SrcChild->hasAnyPredicate()) if (SrcChild->hasAnyPredicate())
return failedImport("Src pattern child has predicate"); return failedImport("Src pattern child has predicate (" +
explainPredicates(SrcChild) + ")");
ArrayRef<EEVT::TypeSet> ChildTypes = SrcChild->getExtTypes(); ArrayRef<EEVT::TypeSet> ChildTypes = SrcChild->getExtTypes();
if (ChildTypes.size() != 1) if (ChildTypes.size() != 1)
@ -1366,8 +1427,8 @@ Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher,
if (ChildRec->isSubClassOf("ComplexPattern")) { if (ChildRec->isSubClassOf("ComplexPattern")) {
const auto &ComplexPattern = ComplexPatternEquivs.find(ChildRec); const auto &ComplexPattern = ComplexPatternEquivs.find(ChildRec);
if (ComplexPattern == ComplexPatternEquivs.end()) if (ComplexPattern == ComplexPatternEquivs.end())
return failedImport( return failedImport("SelectionDAG ComplexPattern (" +
"SelectionDAG ComplexPattern not mapped to GlobalISel"); ChildRec->getName() + ") not mapped to GlobalISel");
const auto &Predicate = OM.addPredicate<ComplexPatternOperandMatcher>( const auto &Predicate = OM.addPredicate<ComplexPatternOperandMatcher>(
OM, *ComplexPattern->second); OM, *ComplexPattern->second);
@ -1375,6 +1436,11 @@ Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher,
return Error::success(); return Error::success();
} }
if (ChildRec->isSubClassOf("ImmLeaf")) {
return failedImport(
"Src pattern child def is an unsupported tablegen class (ImmLeaf)");
}
return failedImport( return failedImport(
"Src pattern child def is an unsupported tablegen class"); "Src pattern child def is an unsupported tablegen class");
} }
@ -1401,7 +1467,8 @@ Error GlobalISelEmitter::importExplicitUseRenderer(
// Otherwise, we're looking for a bog-standard RegisterClass operand. // Otherwise, we're looking for a bog-standard RegisterClass operand.
if (DstChild->hasAnyPredicate()) if (DstChild->hasAnyPredicate())
return failedImport("Dst pattern child has predicate"); return failedImport("Dst pattern child has predicate (" +
explainPredicates(DstChild) + ")");
if (auto *ChildDefInit = dyn_cast<DefInit>(DstChild->getLeafValue())) { if (auto *ChildDefInit = dyn_cast<DefInit>(DstChild->getLeafValue())) {
auto *ChildRec = ChildDefInit->getDef(); auto *ChildRec = ChildDefInit->getDef();
@ -1440,6 +1507,10 @@ Error GlobalISelEmitter::importExplicitUseRenderer(
return Error::success(); return Error::success();
} }
if (ChildRec->isSubClassOf("SDNodeXForm"))
return failedImport("Dst pattern child def is an unsupported tablegen "
"class (SDNodeXForm)");
return failedImport( return failedImport(
"Dst pattern child def is an unsupported tablegen class"); "Dst pattern child def is an unsupported tablegen class");
} }
@ -1451,8 +1522,12 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
RuleMatcher &M, const TreePatternNode *Dst, RuleMatcher &M, const TreePatternNode *Dst,
const InstructionMatcher &InsnMatcher) const { const InstructionMatcher &InsnMatcher) const {
Record *DstOp = Dst->getOperator(); Record *DstOp = Dst->getOperator();
if (!DstOp->isSubClassOf("Instruction")) if (!DstOp->isSubClassOf("Instruction")) {
if (DstOp->isSubClassOf("ValueType"))
return failedImport(
"Pattern operator isn't an instruction (it's a ValueType)");
return failedImport("Pattern operator isn't an instruction"); return failedImport("Pattern operator isn't an instruction");
}
auto &DstI = Target.getInstruction(DstOp); auto &DstI = Target.getInstruction(DstOp);
auto &DstMIBuilder = M.addAction<BuildMIAction>(&DstI, InsnMatcher); auto &DstMIBuilder = M.addAction<BuildMIAction>(&DstI, InsnMatcher);
@ -1549,10 +1624,12 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
TreePatternNode *Dst = P.getDstPattern(); TreePatternNode *Dst = P.getDstPattern();
// If the root of either pattern isn't a simple operator, ignore it. // If the root of either pattern isn't a simple operator, ignore it.
if (!isTrivialOperatorNode(Dst)) if (auto Err = isTrivialOperatorNode(Dst))
return failedImport("Dst pattern root isn't a trivial operator"); return failedImport("Dst pattern root isn't a trivial operator (" +
if (!isTrivialOperatorNode(Src)) toString(std::move(Err)) + ")");
return failedImport("Src pattern root isn't a trivial operator"); if (auto Err = isTrivialOperatorNode(Src))
return failedImport("Src pattern root isn't a trivial operator (" +
toString(std::move(Err)) + ")");
// Start with the defined operands (i.e., the results of the root operator). // Start with the defined operands (i.e., the results of the root operator).
Record *DstOp = Dst->getOperator(); Record *DstOp = Dst->getOperator();
@ -1561,7 +1638,9 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
auto &DstI = Target.getInstruction(DstOp); auto &DstI = Target.getInstruction(DstOp);
if (DstI.Operands.NumDefs != Src->getExtTypes().size()) if (DstI.Operands.NumDefs != Src->getExtTypes().size())
return failedImport("Src pattern results and dst MI defs are different"); return failedImport("Src pattern results and dst MI defs are different (" +
to_string(Src->getExtTypes().size()) + " def(s) vs " +
to_string(DstI.Operands.NumDefs) + " def(s))");
InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher(); InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher();
auto InsnMatcherOrError = createAndImportSelDAGMatcher(InsnMatcherTemp, Src); auto InsnMatcherOrError = createAndImportSelDAGMatcher(InsnMatcherTemp, Src);