continue pushing tblgen's support for nodes with multiple

results forward.  We can now handle an instruction that 
produces one implicit def and one result instead of one or
the other when not at the root of the pattern.

llvm-svn: 99725
This commit is contained in:
Chris Lattner 2010-03-27 19:15:02 +00:00
parent 97752f7c95
commit d44966f26d
2 changed files with 44 additions and 40 deletions

View File

@ -775,10 +775,9 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
if (Operator->isSubClassOf("Instruction")) { if (Operator->isSubClassOf("Instruction")) {
CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator);
// FIXME: Handle implicit defs right. // FIXME: Should allow access to all the results here.
if (InstInfo.NumDefs != 0) unsigned NumDefsToAdd = InstInfo.NumDefs ? 1 : 0;
return 1; // FIXME: Handle inst results right!
if (!InstInfo.ImplicitDefs.empty()) { if (!InstInfo.ImplicitDefs.empty()) {
// Add on one implicit def if it has a resolvable type. // Add on one implicit def if it has a resolvable type.
@ -787,9 +786,9 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
const std::vector<MVT::SimpleValueType> &RegVTs = const std::vector<MVT::SimpleValueType> &RegVTs =
CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef); CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef);
if (RegVTs.size() == 1) if (RegVTs.size() == 1)
return 1; return NumDefsToAdd+1;
} }
return 0; return NumDefsToAdd;
} }
if (Operator->isSubClassOf("SDNodeXForm")) if (Operator->isSubClassOf("SDNodeXForm"))
@ -1250,21 +1249,20 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
if (getOperator()->isSubClassOf("Instruction")) { if (getOperator()->isSubClassOf("Instruction")) {
const DAGInstruction &Inst = CDP.getInstruction(getOperator()); const DAGInstruction &Inst = CDP.getInstruction(getOperator());
unsigned ResNo = 0;
assert(Inst.getNumResults() <= 1 &&
"FIXME: Only supports zero or one result instrs!");
CodeGenInstruction &InstInfo = CodeGenInstruction &InstInfo =
CDP.getTargetInfo().getInstruction(getOperator()); CDP.getTargetInfo().getInstruction(getOperator());
EEVT::TypeSet ResultType; bool MadeChange = false;
// Apply the result type to the node // Apply the result types to the node, these come from the things in the
if (InstInfo.NumDefs != 0) { // # of elements in (outs) list // (outs) list of the instruction.
Record *ResultNode = Inst.getResult(0); // FIXME: Cap at one result so far.
unsigned NumResultsToAdd = InstInfo.NumDefs ? 1 : 0;
for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) {
Record *ResultNode = Inst.getResult(ResNo);
if (ResultNode->isSubClassOf("PointerLikeRegClass")) { if (ResultNode->isSubClassOf("PointerLikeRegClass")) {
ResultType = EEVT::TypeSet(MVT::iPTR, TP); MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP);
} else if (ResultNode->getName() == "unknown") { } else if (ResultNode->getName() == "unknown") {
// Nothing to do. // Nothing to do.
} else { } else {
@ -1272,26 +1270,23 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
"Operands should be register classes!"); "Operands should be register classes!");
const CodeGenRegisterClass &RC = const CodeGenRegisterClass &RC =
CDP.getTargetInfo().getRegisterClass(ResultNode); CDP.getTargetInfo().getRegisterClass(ResultNode);
ResultType = RC.getValueTypes(); MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP);
} }
} else if (!InstInfo.ImplicitDefs.empty()) { }
// If the instruction has implicit defs, the first one defines the result
// type. // If the instruction has implicit defs, we apply the first one as a result.
// FIXME: This sucks, it should apply all implicit defs.
if (!InstInfo.ImplicitDefs.empty()) {
unsigned ResNo = NumResultsToAdd;
Record *FirstImplicitDef = InstInfo.ImplicitDefs[0]; Record *FirstImplicitDef = InstInfo.ImplicitDefs[0];
assert(FirstImplicitDef->isSubClassOf("Register")); assert(FirstImplicitDef->isSubClassOf("Register"));
const std::vector<MVT::SimpleValueType> &RegVTs = const std::vector<MVT::SimpleValueType> &RegVTs =
CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef); CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef);
if (RegVTs.size() == 1) // FIXME: Generalize. if (RegVTs.size() == 1) // FIXME: Generalize.
ResultType = EEVT::TypeSet(RegVTs); MadeChange |= UpdateNodeType(ResNo, EEVT::TypeSet(RegVTs), TP);
} else {
// Otherwise, the instruction produces no value result.
} }
bool MadeChange = false;
if (!ResultType.isCompletelyUnknown())
MadeChange |= UpdateNodeType(ResNo, ResultType, TP);
// If this is an INSERT_SUBREG, constrain the source and destination VTs to // If this is an INSERT_SUBREG, constrain the source and destination VTs to
// be the same. // be the same.
if (getOperator()->getName() == "INSERT_SUBREG") { if (getOperator()->getName() == "INSERT_SUBREG") {
@ -1319,17 +1314,17 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
MVT::SimpleValueType VT; MVT::SimpleValueType VT;
TreePatternNode *Child = getChild(ChildNo++); TreePatternNode *Child = getChild(ChildNo++);
assert(Child->getNumTypes() == 1 && "Unknown case?"); unsigned ChildResNo = 0; // Instructions always use res #0 of their op.
if (OperandNode->isSubClassOf("RegisterClass")) { if (OperandNode->isSubClassOf("RegisterClass")) {
const CodeGenRegisterClass &RC = const CodeGenRegisterClass &RC =
CDP.getTargetInfo().getRegisterClass(OperandNode); CDP.getTargetInfo().getRegisterClass(OperandNode);
MadeChange |= Child->UpdateNodeType(0, RC.getValueTypes(), TP); MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP);
} else if (OperandNode->isSubClassOf("Operand")) { } else if (OperandNode->isSubClassOf("Operand")) {
VT = getValueType(OperandNode->getValueAsDef("Type")); VT = getValueType(OperandNode->getValueAsDef("Type"));
MadeChange |= Child->UpdateNodeType(0, VT, TP); MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP);
} else if (OperandNode->isSubClassOf("PointerLikeRegClass")) { } else if (OperandNode->isSubClassOf("PointerLikeRegClass")) {
MadeChange |= Child->UpdateNodeType(0, MVT::iPTR, TP); MadeChange |= Child->UpdateNodeType(ChildResNo, MVT::iPTR, TP);
} else if (OperandNode->getName() == "unknown") { } else if (OperandNode->getName() == "unknown") {
// Nothing to do. // Nothing to do.
} else { } else {

View File

@ -687,9 +687,19 @@ 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.
EmitResultOperand(N->getChild(ChildNo), InstOps); 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; ++ChildNo;
} }
@ -711,12 +721,8 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// Determine the result types. // Determine the result types.
SmallVector<MVT::SimpleValueType, 4> ResultVTs; SmallVector<MVT::SimpleValueType, 4> ResultVTs;
if (N->getNumTypes()) { for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i)
// FIXME2: If the node has multiple results, we should add them. For now, ResultVTs.push_back(N->getType(i));
// preserve existing behavior?!
assert(N->getNumTypes() == 1);
ResultVTs.push_back(N->getType(0));
}
// If this is the root instruction of a pattern that has physical registers in // If this is the root instruction of a pattern that has physical registers in
// its result pattern, add output VTs for them. For example, X86 has: // its result pattern, add output VTs for them. For example, X86 has:
@ -727,7 +733,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// If the root came from an implicit def in the instruction handling stuff, // If the root came from an implicit def in the instruction handling stuff,
// don't re-add it. // don't re-add it.
Record *HandledReg = 0; Record *HandledReg = 0;
if (NumResults == 0 && N->getNumTypes() != 0 && if (N->getNumTypes() != 0 &&
!II.ImplicitDefs.empty()) !II.ImplicitDefs.empty())
HandledReg = II.ImplicitDefs[0]; HandledReg = II.ImplicitDefs[0];
@ -762,6 +768,9 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
bool NodeHasMemRefs = bool NodeHasMemRefs =
isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP); isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP);
assert((!ResultVTs.empty() || TreeHasOutFlag || NodeHasChain) &&
"Node has no result");
AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(), AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(),
ResultVTs.data(), ResultVTs.size(), ResultVTs.data(), ResultVTs.size(),
InstOps.data(), InstOps.size(), InstOps.data(), InstOps.size(),