[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:
parent
2d33869806
commit
d0656a3af1
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue