Extend TableGen instruction selection matcher to improve handling

of complex instruction operands (e.g. address modes).

Currently, if a Pat pattern creates an instruction that has a complex
operand (i.e. one that consists of multiple sub-operands at the MI
level), this operand must match a ComplexPattern DAG pattern with the
correct number of output operands.

This commit extends TableGen to alternatively allow match a complex
operands against multiple separate operands at the DAG level.

This allows using Pat patterns to match pre-increment nodes like
pre_store (which must have separate operands at the DAG level) onto
an instruction pattern that uses a multi-operand memory operand,
like the following example on PowerPC (will be committed as a
follow-on patch):

  def STWU  : DForm_1<37, (outs ptr_rc:$ea_res), (ins GPRC:$rS, memri:$dst),
                    "stwu $rS, $dst", LdStStoreUpd, []>,
                    RegConstraint<"$dst.reg = $ea_res">, NoEncode<"$ea_res">;

  def : Pat<(pre_store GPRC:$rS, ptr_rc:$ptrreg, iaddroff:$ptroff),
            (STWU GPRC:$rS, iaddroff:$ptroff, ptr_rc:$ptrreg)>;

Here, the pair of "ptroff" and "ptrreg" operands is matched onto the
complex operand "dst" of class "memri" in the "STWU" instruction.

Approved by Jakob Stoklund Olesen.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177428 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ulrich Weigand
2013-03-19 19:51:09 +00:00
parent 880d82e3db
commit ec8d1a5b72
3 changed files with 78 additions and 11 deletions

View File

@ -1038,6 +1038,24 @@ for your target. It has the following strengths:
are used to manipulate the input immediate (in this case, take the high or low are used to manipulate the input immediate (in this case, take the high or low
16-bits of the immediate). 16-bits of the immediate).
* When using the 'Pat' class to map a pattern to an instruction that has one
or more complex operands (like e.g. `X86 addressing mode`_), the pattern may
either specify the operand as a whole using a ``ComplexPattern``, or else it
may specify the components of the complex operand separately. The latter is
done e.g. for pre-increment instructions by the PowerPC back end:
::
def STWU : DForm_1<37, (outs ptr_rc:$ea_res), (ins GPRC:$rS, memri:$dst),
"stwu $rS, $dst", LdStStoreUpd, []>,
RegConstraint<"$dst.reg = $ea_res">, NoEncode<"$ea_res">;
def : Pat<(pre_store GPRC:$rS, ptr_rc:$ptrreg, iaddroff:$ptroff),
(STWU GPRC:$rS, iaddroff:$ptroff, ptr_rc:$ptrreg)>;
Here, the pair of ``ptroff`` and ``ptrreg`` operands is matched onto the
complex operand ``dst`` of class ``memri`` in the ``STWU`` instruction.
* While the system does automate a lot, it still allows you to write custom C++ * While the system does automate a lot, it still allows you to write custom C++
code to match special cases if there is something that is hard to code to match special cases if there is something that is hard to
express. express.

View File

@ -1654,8 +1654,42 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
TreePatternNode *Child = getChild(ChildNo++); TreePatternNode *Child = getChild(ChildNo++);
unsigned ChildResNo = 0; // Instructions always use res #0 of their op. unsigned ChildResNo = 0; // Instructions always use res #0 of their op.
// If the operand has sub-operands, they may be provided by distinct
// child patterns, so attempt to match each sub-operand separately.
if (OperandNode->isSubClassOf("Operand")) {
DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo");
if (unsigned NumArgs = MIOpInfo->getNumArgs()) {
// But don't do that if the whole operand is being provided by
// a single ComplexPattern.
const ComplexPattern *AM = Child->getComplexPatternInfo(CDP);
if (!AM || AM->getNumOperands() < NumArgs) {
// Match first sub-operand against the child we already have.
Record *SubRec = cast<DefInit>(MIOpInfo->getArg(0))->getDef();
MadeChange |=
Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP);
// And the remaining sub-operands against subsequent children.
for (unsigned Arg = 1; Arg < NumArgs; ++Arg) {
if (ChildNo >= getNumChildren()) {
TP.error("Instruction '" + getOperator()->getName() +
"' expects more operands than were provided.");
return false;
}
Child = getChild(ChildNo++);
SubRec = cast<DefInit>(MIOpInfo->getArg(Arg))->getDef();
MadeChange |=
Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP);
}
continue;
}
}
}
// If we didn't match by pieces above, attempt to match the whole
// operand now.
MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP); MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP);
MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
} }
if (ChildNo != getNumChildren()) { if (ChildNo != getNumChildren()) {
@ -1664,6 +1698,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
return false; return false;
} }
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
return MadeChange; return MadeChange;
} }

View File

@ -734,20 +734,33 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
continue; continue;
} }
const TreePatternNode *Child = N->getChild(ChildNo);
// Otherwise this is a normal operand or a predicate operand without // Otherwise this is a normal operand or a predicate operand without
// 'execute always'; emit it. // 'execute always'; emit it.
unsigned BeforeAddingNumOps = InstOps.size();
EmitResultOperand(Child, InstOps);
assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands");
// If the operand is an instruction and it produced multiple results, just // For operands with multiple sub-operands we may need to emit
// take the first one. // multiple child patterns to cover them all. However, ComplexPattern
if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction")) // children may themselves emit multiple MI operands.
InstOps.resize(BeforeAddingNumOps+1); unsigned NumSubOps = 1;
if (OperandNode->isSubClassOf("Operand")) {
DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo");
if (unsigned NumArgs = MIOpInfo->getNumArgs())
NumSubOps = NumArgs;
}
++ChildNo; unsigned FinalNumOps = InstOps.size() + NumSubOps;
while (InstOps.size() < FinalNumOps) {
const TreePatternNode *Child = N->getChild(ChildNo);
unsigned BeforeAddingNumOps = InstOps.size();
EmitResultOperand(Child, InstOps);
assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands");
// If the operand is an instruction and it produced multiple results, just
// take the first one.
if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction"))
InstOps.resize(BeforeAddingNumOps+1);
++ChildNo;
}
} }
// If this node has input glue or explicitly specified input physregs, we // If this node has input glue or explicitly specified input physregs, we