mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-25 16:24:23 +00:00
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:
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user