GlobalISel/TableGen: Don't skip REG_SEQUENCE based on patterns
This partially adds support for patterns with REG_SEQUENCE. The source patterns are now accepted, but the pattern is still rejected due to missing support for the instruction renderer. llvm-svn: 370920
This commit is contained in:
parent
240a2e25c6
commit
38fb34443c
@ -3931,8 +3931,8 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
|
||||
// We need to make sure that when we import an INSERT_SUBREG as a
|
||||
// subinstruction that it ends up being constrained to the correct super
|
||||
// register and subregister classes.
|
||||
if (Target.getInstruction(Dst->getOperator()).TheDef->getName() ==
|
||||
"INSERT_SUBREG") {
|
||||
auto OpName = Target.getInstruction(Dst->getOperator()).TheDef->getName();
|
||||
if (OpName == "INSERT_SUBREG") {
|
||||
auto SubClass = inferRegClassFromPattern(Dst->getChild(1));
|
||||
if (!SubClass)
|
||||
return failedImport(
|
||||
@ -3956,23 +3956,22 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
|
||||
|
||||
// Similar to INSERT_SUBREG, we also have to handle SUBREG_TO_REG as a
|
||||
// subinstruction.
|
||||
if (Target.getInstruction(Dst->getOperator()).TheDef->getName() ==
|
||||
"SUBREG_TO_REG") {
|
||||
auto SubClass = inferRegClassFromPattern(Dst->getChild(1));
|
||||
if (!SubClass)
|
||||
return failedImport(
|
||||
if (OpName == "SUBREG_TO_REG") {
|
||||
auto SubClass = inferRegClassFromPattern(Dst->getChild(1));
|
||||
if (!SubClass)
|
||||
return failedImport(
|
||||
"Cannot infer register class from SUBREG_TO_REG child #1");
|
||||
auto SuperClass = inferSuperRegisterClass(Dst->getExtType(0),
|
||||
Dst->getChild(2));
|
||||
if (!SuperClass)
|
||||
return failedImport(
|
||||
auto SuperClass = inferSuperRegisterClass(Dst->getExtType(0),
|
||||
Dst->getChild(2));
|
||||
if (!SuperClass)
|
||||
return failedImport(
|
||||
"Cannot infer register class for SUBREG_TO_REG operand #0");
|
||||
M.insertAction<ConstrainOperandToRegClassAction>(
|
||||
M.insertAction<ConstrainOperandToRegClassAction>(
|
||||
InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass);
|
||||
M.insertAction<ConstrainOperandToRegClassAction>(
|
||||
M.insertAction<ConstrainOperandToRegClassAction>(
|
||||
InsertPt, DstMIBuilder.getInsnID(), 2, **SubClass);
|
||||
return InsertPtOrError.get();
|
||||
}
|
||||
return InsertPtOrError.get();
|
||||
}
|
||||
|
||||
M.insertAction<ConstrainOperandsToDefinitionAction>(InsertPt,
|
||||
DstMIBuilder.getInsnID());
|
||||
@ -4193,10 +4192,11 @@ GlobalISelEmitter::inferRegClassFromPattern(TreePatternNode *N) {
|
||||
// Handle any special-case instructions which we can safely infer register
|
||||
// classes from.
|
||||
StringRef InstName = Inst.TheDef->getName();
|
||||
if (InstName == "COPY_TO_REGCLASS") {
|
||||
bool IsRegSequence = InstName == "REG_SEQUENCE";
|
||||
if (IsRegSequence || InstName == "COPY_TO_REGCLASS") {
|
||||
// If we have a COPY_TO_REGCLASS, then we need to handle it specially. It
|
||||
// has the desired register class as the first child.
|
||||
TreePatternNode *RCChild = N->getChild(1);
|
||||
TreePatternNode *RCChild = N->getChild(IsRegSequence ? 0 : 1);
|
||||
if (!RCChild->isLeaf())
|
||||
return None;
|
||||
return getRegClassFromLeaf(RCChild);
|
||||
@ -4349,6 +4349,8 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
return failedImport("Pattern operator isn't an instruction");
|
||||
|
||||
auto &DstI = Target.getInstruction(DstOp);
|
||||
StringRef DstIName = DstI.TheDef->getName();
|
||||
|
||||
if (DstI.Operands.NumDefs != Src->getExtTypes().size())
|
||||
return failedImport("Src pattern results and dst MI defs are different (" +
|
||||
to_string(Src->getExtTypes().size()) + " def(s) vs " +
|
||||
@ -4362,13 +4364,17 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
|
||||
const auto &DstIOperand = DstI.Operands[OpIdx];
|
||||
Record *DstIOpRec = DstIOperand.Rec;
|
||||
if (DstI.TheDef->getName() == "COPY_TO_REGCLASS") {
|
||||
if (DstIName == "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 (DstI.TheDef->getName() == "EXTRACT_SUBREG") {
|
||||
} else if (DstIName == "REG_SEQUENCE") {
|
||||
DstIOpRec = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());
|
||||
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");
|
||||
|
||||
@ -4378,7 +4384,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
|
||||
if (DstIOpRec == nullptr)
|
||||
return failedImport("EXTRACT_SUBREG operand #0 isn't a register class");
|
||||
} else if (DstI.TheDef->getName() == "INSERT_SUBREG") {
|
||||
} else if (DstIName == "INSERT_SUBREG") {
|
||||
auto MaybeSuperClass = inferSuperRegisterClassForNode(
|
||||
VTy, Dst->getChild(0), Dst->getChild(2));
|
||||
if (!MaybeSuperClass)
|
||||
@ -4393,7 +4399,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
OM.addPredicate<RegisterBankOperandMatcher>(**MaybeSuperClass);
|
||||
++OpIdx;
|
||||
continue;
|
||||
} else if (DstI.TheDef->getName() == "SUBREG_TO_REG") {
|
||||
} else if (DstIName == "SUBREG_TO_REG") {
|
||||
auto MaybeRegClass = inferSuperRegisterClass(VTy, Dst->getChild(2));
|
||||
if (!MaybeRegClass)
|
||||
return failedImport(
|
||||
@ -4432,7 +4438,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
|
||||
// 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") {
|
||||
if (DstIName == "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 =
|
||||
@ -4450,7 +4456,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
return std::move(M);
|
||||
}
|
||||
|
||||
if (DstI.TheDef->getName() == "EXTRACT_SUBREG") {
|
||||
if (DstIName == "EXTRACT_SUBREG") {
|
||||
// EXTRACT_SUBREG selects into a subregister COPY but unlike most
|
||||
// instructions, the result register class is controlled by the
|
||||
// subregisters of the operand. As a result, we must constrain the result
|
||||
@ -4493,7 +4499,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
return std::move(M);
|
||||
}
|
||||
|
||||
if (DstI.TheDef->getName() == "INSERT_SUBREG") {
|
||||
if (DstIName == "INSERT_SUBREG") {
|
||||
assert(Src->getExtTypes().size() == 1 &&
|
||||
"Expected Src of INSERT_SUBREG to have one result type");
|
||||
// We need to constrain the destination, a super regsister source, and a
|
||||
@ -4514,7 +4520,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
return std::move(M);
|
||||
}
|
||||
|
||||
if (DstI.TheDef->getName() == "SUBREG_TO_REG") {
|
||||
if (DstIName == "SUBREG_TO_REG") {
|
||||
// We need to constrain the destination and subregister source.
|
||||
assert(Src->getExtTypes().size() == 1 &&
|
||||
"Expected Src of SUBREG_TO_REG to have one result type");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user