Change PatternCodeEmitter to emit code into a buffer instead of emitting it

directly to the output file.  This makes things simple because the code doesn't
have to worry about indentation or the case when there is no goto.  It also
allows us to indent the code better without touching everything :)


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25756 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2006-01-28 20:31:24 +00:00
parent c4013d6772
commit 8a0604b523

View File

@ -1830,8 +1830,7 @@ private:
// Matched instruction. // Matched instruction.
TreePatternNode *Instruction; TreePatternNode *Instruction;
unsigned PatternNo; unsigned PatternNo;
bool GotosFail;
std::ostream &OS;
// Node to name mapping // Node to name mapping
std::map<std::string, std::string> VariableMap; std::map<std::string, std::string> VariableMap;
// Node to operator mapping // Node to operator mapping
@ -1839,16 +1838,30 @@ private:
// Names of all the folded nodes which produce chains. // Names of all the folded nodes which produce chains.
std::vector<std::pair<std::string, unsigned> > FoldedChains; std::vector<std::pair<std::string, unsigned> > FoldedChains;
std::set<std::string> Duplicates; std::set<std::string> Duplicates;
unsigned TmpNo;
/// GeneratedCode - This is the buffer that we emit code to. The first bool
/// indicates whether this is an exit predicate (something that should be
/// tested, and if true, the match fails) [when true] or normal code to emit
/// [when false].
std::vector<std::pair<bool, std::string> > &GeneratedCode;
unsigned TmpNo;
void emitCheck(const std::string &S) {
if (!S.empty())
GeneratedCode.push_back(std::make_pair(true, S));
}
void emitCode(const std::string &S) {
if (!S.empty())
GeneratedCode.push_back(std::make_pair(false, S));
}
public: public:
PatternCodeEmitter(DAGISelEmitter &ise, ListInit *preds, PatternCodeEmitter(DAGISelEmitter &ise, ListInit *preds,
TreePatternNode *pattern, TreePatternNode *instr, TreePatternNode *pattern, TreePatternNode *instr,
unsigned PatNum, std::ostream &os) : unsigned PatNum,
ISE(ise), Predicates(preds), Pattern(pattern), Instruction(instr), std::vector<std::pair<bool, std::string> > &gc)
PatternNo(PatNum), GotosFail(false), OS(os), TmpNo(0) {} : ISE(ise), Predicates(preds), Pattern(pattern), Instruction(instr),
PatternNo(PatNum), GeneratedCode(gc), TmpNo(0) {}
bool UsesFailLabel() { return GotosFail; }
/// EmitMatchCode - Emit a matcher for N, going to the label for PatternNo /// EmitMatchCode - Emit a matcher for N, going to the label for PatternNo
/// if the match fails. At this point, we already know that the opcode for N /// if the match fails. At this point, we already know that the opcode for N
@ -1858,33 +1871,27 @@ public:
// Emit instruction predicates. Each predicate is just a string for now. // Emit instruction predicates. Each predicate is just a string for now.
if (isRoot) { if (isRoot) {
std::string PredicateCheck;
for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) { for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) { if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
Record *Def = Pred->getDef(); Record *Def = Pred->getDef();
if (Def->isSubClassOf("Predicate")) { if (!Def->isSubClassOf("Predicate")) {
if (i == 0)
OS << " if (";
else
OS << " && ";
OS << "!(" << Def->getValueAsString("CondString") << ")";
if (i == e-1) {
OS << ") goto P" << PatternNo << "Fail;\n";
GotosFail = true;
}
} else {
Def->dump(); Def->dump();
assert(0 && "Unknown predicate type!"); assert(0 && "Unknown predicate type!");
} }
if (!PredicateCheck.empty())
PredicateCheck += " && ";
PredicateCheck += "!(" + Def->getValueAsString("CondString") + ")";
} }
} }
emitCheck(PredicateCheck);
} }
if (N->isLeaf()) { if (N->isLeaf()) {
if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
OS << " if (cast<ConstantSDNode>(" << RootName emitCheck("cast<ConstantSDNode>(" + RootName +
<< ")->getSignExtended() != " << II->getValue() << ")\n" ")->getSignExtended() != " + itostr(II->getValue()));
<< " goto P" << PatternNo << "Fail;\n";
GotosFail = true;
return; return;
} else if (!NodeIsComplexPattern(N)) { } else if (!NodeIsComplexPattern(N)) {
assert(0 && "Cannot match this as a leaf value!"); assert(0 && "Cannot match this as a leaf value!");
@ -1903,9 +1910,7 @@ public:
// we already have checked that the first reference is valid, we don't // we already have checked that the first reference is valid, we don't
// have to recursively match it, just check that it's the same as the // have to recursively match it, just check that it's the same as the
// previously named thing. // previously named thing.
OS << " if (" << VarMapEntry << " != " << RootName emitCheck(VarMapEntry + " != " + RootName);
<< ") goto P" << PatternNo << "Fail;\n";
GotosFail = true;
return; return;
} }
@ -1925,35 +1930,27 @@ public:
OpNo = 1; OpNo = 1;
if (!isRoot) { if (!isRoot) {
const SDNodeInfo &CInfo = ISE.getSDNodeInfo(N->getOperator()); const SDNodeInfo &CInfo = ISE.getSDNodeInfo(N->getOperator());
OS << " if (!" << RootName << ".hasOneUse()) goto P" // Multiple uses of actual result?
<< PatternNo << "Fail; // Multiple uses of actual result?\n"; emitCheck("!" + RootName + ".hasOneUse()");
GotosFail = true;
EmittedUseCheck = true; EmittedUseCheck = true;
// hasOneUse() check is not strong enough. If the original node has // hasOneUse() check is not strong enough. If the original node has
// already been selected, it may have been replaced with another. // already been selected, it may have been replaced with another.
for (unsigned j = 0; j < CInfo.getNumResults(); j++) { for (unsigned j = 0; j != CInfo.getNumResults(); j++)
OS << " if (CodeGenMap.count(" << RootName emitCheck("CodeGenMap.count(" + RootName + ".getValue(" + utostr(j) +
<< ".getValue(" << j << "))) goto P" "))");
<< PatternNo << "Fail; // Already selected?\n";
GotosFail = true;
}
EmittedSlctedCheck = true; EmittedSlctedCheck = true;
if (NodeHasChain) { if (NodeHasChain)
OS << " if (CodeGenMap.count(" << RootName emitCheck("CodeGenMap.count(" + RootName + ".getValue(" +
<< ".getValue(" << CInfo.getNumResults() << "))) goto P" utostr(CInfo.getNumResults()) + "))");
<< PatternNo << "Fail; // Already selected for a chain use?\n";
GotosFail = true;
}
} }
if (NodeHasChain) { if (NodeHasChain) {
if (!FoundChain) { if (!FoundChain) {
OS << " SDOperand Chain = " << RootName << ".getOperand(0);\n"; emitCode("SDOperand Chain = " + RootName + ".getOperand(0);");
FoundChain = true; FoundChain = true;
} else { } else {
OS << " if (Chain.Val == " << RootName << ".Val)\n"; emitCheck("Chain.Val != " + RootName + ".Val");
OS << " Chain = " << RootName << ".getOperand(0);\n"; emitCode("Chain = " + RootName + ".getOperand(0);");
OS << " else\n";
OS << " goto P" << PatternNo << "Fail;\n";
} }
} }
} }
@ -1968,37 +1965,31 @@ public:
PatternHasProperty(N, SDNodeInfo::SDNPOutFlag, ISE))) { PatternHasProperty(N, SDNodeInfo::SDNPOutFlag, ISE))) {
const SDNodeInfo &CInfo = ISE.getSDNodeInfo(N->getOperator()); const SDNodeInfo &CInfo = ISE.getSDNodeInfo(N->getOperator());
if (!EmittedUseCheck) { if (!EmittedUseCheck) {
OS << " if (!" << RootName << ".hasOneUse()) goto P" // Multiple uses of actual result?
<< PatternNo << "Fail; // Multiple uses of actual result?\n"; emitCheck("!" + RootName + ".hasOneUse()");
GotosFail = true;
} }
if (!EmittedSlctedCheck) if (!EmittedSlctedCheck)
// hasOneUse() check is not strong enough. If the original node has // hasOneUse() check is not strong enough. If the original node has
// already been selected, it may have been replaced with another. // already been selected, it may have been replaced with another.
for (unsigned j = 0; j < CInfo.getNumResults(); j++) { for (unsigned j = 0; j < CInfo.getNumResults(); j++)
OS << " if (CodeGenMap.count(" << RootName emitCheck("CodeGenMap.count(" + RootName + ".getValue(" + utostr(j) +
<< ".getValue(" << j << "))) goto P" "))");
<< PatternNo << "Fail; // Already selected?\n";
GotosFail = true;
}
} }
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) { for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
OS << " SDOperand " << RootName << OpNo << " = " emitCode("SDOperand " + RootName + utostr(OpNo) + " = " +
<< RootName << ".getOperand(" << OpNo << ");\n"; RootName + ".getOperand(" +utostr(OpNo) + ");");
TreePatternNode *Child = N->getChild(i); TreePatternNode *Child = N->getChild(i);
if (!Child->isLeaf()) { if (!Child->isLeaf()) {
// If it's not a leaf, recursively match. // If it's not a leaf, recursively match.
const SDNodeInfo &CInfo = ISE.getSDNodeInfo(Child->getOperator()); const SDNodeInfo &CInfo = ISE.getSDNodeInfo(Child->getOperator());
OS << " if (" << RootName << OpNo << ".getOpcode() != " emitCheck(RootName + utostr(OpNo) + ".getOpcode() != " +
<< CInfo.getEnumName() << ") goto P" << PatternNo << "Fail;\n"; CInfo.getEnumName());
GotosFail = true;
EmitMatchCode(Child, RootName + utostr(OpNo), FoundChain); EmitMatchCode(Child, RootName + utostr(OpNo), FoundChain);
if (NodeHasProperty(Child, SDNodeInfo::SDNPHasChain, ISE)) { if (NodeHasProperty(Child, SDNodeInfo::SDNPHasChain, ISE))
FoldedChains.push_back(std::make_pair(RootName + utostr(OpNo), FoldedChains.push_back(std::make_pair(RootName + utostr(OpNo),
CInfo.getNumResults())); CInfo.getNumResults()));
}
} else { } else {
// If this child has a name associated with it, capture it in VarMap. If // If this child has a name associated with it, capture it in VarMap. If
// we already saw this in the pattern, emit code to verify dagness. // we already saw this in the pattern, emit code to verify dagness.
@ -2011,9 +2002,7 @@ public:
// Since we already have checked that the first reference is valid, // Since we already have checked that the first reference is valid,
// we don't have to recursively match it, just check that it's the // we don't have to recursively match it, just check that it's the
// same as the previously named thing. // same as the previously named thing.
OS << " if (" << VarMapEntry << " != " << RootName << OpNo emitCheck(VarMapEntry + " != " + RootName + utostr(OpNo));
<< ") goto P" << PatternNo << "Fail;\n";
GotosFail = true;
Duplicates.insert(RootName + utostr(OpNo)); Duplicates.insert(RootName + utostr(OpNo));
continue; continue;
} }
@ -2032,17 +2021,12 @@ public:
// Place holder for SRCVALUE nodes. Nothing to do here. // Place holder for SRCVALUE nodes. Nothing to do here.
} else if (LeafRec->isSubClassOf("ValueType")) { } else if (LeafRec->isSubClassOf("ValueType")) {
// Make sure this is the specified value type. // Make sure this is the specified value type.
OS << " if (cast<VTSDNode>(" << RootName << OpNo emitCheck("cast<VTSDNode>(" + RootName + utostr(OpNo) +
<< ")->getVT() != " ")->getVT() != MVT::" + LeafRec->getName());
<< "MVT::" << LeafRec->getName() << ") goto P" << PatternNo
<< "Fail;\n";
GotosFail = true;
} else if (LeafRec->isSubClassOf("CondCode")) { } else if (LeafRec->isSubClassOf("CondCode")) {
// Make sure this is the specified cond code. // Make sure this is the specified cond code.
OS << " if (cast<CondCodeSDNode>(" << RootName << OpNo emitCheck("cast<CondCodeSDNode>(" + RootName + utostr(OpNo) +
<< ")->get() != " << "ISD::" << LeafRec->getName() ")->get() != ISD::" + LeafRec->getName());
<< ") goto P" << PatternNo << "Fail;\n";
GotosFail = true;
} else { } else {
Child->dump(); Child->dump();
std::cerr << " "; std::cerr << " ";
@ -2050,12 +2034,9 @@ public:
} }
} else if (IntInit *II = } else if (IntInit *II =
dynamic_cast<IntInit*>(Child->getLeafValue())) { dynamic_cast<IntInit*>(Child->getLeafValue())) {
OS << " if (!isa<ConstantSDNode>(" << RootName << OpNo emitCheck("!isa<ConstantSDNode>(" + RootName + utostr(OpNo) +
<< ") ||\n" ") || cast<ConstantSDNode>(" + RootName + utostr(OpNo) +
<< " cast<ConstantSDNode>(" << RootName << OpNo ")->getSignExtended() != " + itostr(II->getValue()));
<< ")->getSignExtended() != " << II->getValue() << ")\n"
<< " goto P" << PatternNo << "Fail;\n";
GotosFail = true;
} else { } else {
Child->dump(); Child->dump();
assert(0 && "Unknown leaf type!"); assert(0 && "Unknown leaf type!");
@ -2064,11 +2045,8 @@ public:
} }
// If there is a node predicate for this, emit the call. // If there is a node predicate for this, emit the call.
if (!N->getPredicateFn().empty()) { if (!N->getPredicateFn().empty())
OS << " if (!" << N->getPredicateFn() << "(" << RootName emitCheck("!" + N->getPredicateFn() + "(" + RootName + ".Val)");
<< ".Val)) goto P" << PatternNo << "Fail;\n";
GotosFail = true;
}
} }
/// EmitResultCode - Emit the action for a pattern. Now that it has matched /// EmitResultCode - Emit the action for a pattern. Now that it has matched
@ -2091,59 +2069,61 @@ public:
unsigned NumRes = 1; unsigned NumRes = 1;
if (!N->isLeaf() && N->getOperator()->getName() == "imm") { if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!"); assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
const char *Code;
switch (N->getTypeNum(0)) { switch (N->getTypeNum(0)) {
default: assert(0 && "Unknown type for constant node!"); default: assert(0 && "Unknown type for constant node!");
case MVT::i1: OS << " bool Tmp"; break; case MVT::i1: Code = "bool Tmp"; break;
case MVT::i8: OS << " unsigned char Tmp"; break; case MVT::i8: Code = "unsigned char Tmp"; break;
case MVT::i16: OS << " unsigned short Tmp"; break; case MVT::i16: Code = "unsigned short Tmp"; break;
case MVT::i32: OS << " unsigned Tmp"; break; case MVT::i32: Code = "unsigned Tmp"; break;
case MVT::i64: OS << " uint64_t Tmp"; break; case MVT::i64: Code = "uint64_t Tmp"; break;
} }
OS << ResNo << "C = (unsigned)cast<ConstantSDNode>(" << Val emitCode(Code + utostr(ResNo) + "C = (unsigned)cast<ConstantSDNode>(" +
<< ")->getValue();\n"; Val + ")->getValue();");
OS << " SDOperand Tmp" << utostr(ResNo) emitCode("SDOperand Tmp" + utostr(ResNo) +
<< " = CurDAG->getTargetConstant(Tmp" " = CurDAG->getTargetConstant(Tmp" + utostr(ResNo) +
<< ResNo << "C, MVT::" << getEnumName(N->getTypeNum(0)) << ");\n"; "C, MVT::" + getEnumName(N->getTypeNum(0)) + ");");
} else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){ } else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
Record *Op = OperatorMap[N->getName()]; Record *Op = OperatorMap[N->getName()];
// Transform ExternalSymbol to TargetExternalSymbol // Transform ExternalSymbol to TargetExternalSymbol
if (Op && Op->getName() == "externalsym") { if (Op && Op->getName() == "externalsym") {
OS << " SDOperand Tmp" << ResNo emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
<< " = CurDAG->getTargetExternalSymbol(cast<ExternalSymbolSDNode>(" "ExternalSymbol(cast<ExternalSymbolSDNode>(" +
<< Val << ")->getSymbol(), MVT::" << getEnumName(N->getTypeNum(0)) Val + ")->getSymbol(), MVT::" +
<< ");\n"; getEnumName(N->getTypeNum(0)) + ");");
} else } else {
OS << " SDOperand Tmp" << ResNo << " = " << Val << ";\n"; emitCode("SDOperand Tmp" + utostr(ResNo) + " = " + Val + ";");
}
} else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") { } else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") {
Record *Op = OperatorMap[N->getName()]; Record *Op = OperatorMap[N->getName()];
// Transform GlobalAddress to TargetGlobalAddress // Transform GlobalAddress to TargetGlobalAddress
if (Op && Op->getName() == "globaladdr") { if (Op && Op->getName() == "globaladdr") {
OS << " SDOperand Tmp" << ResNo emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
<< " = CurDAG->getTargetGlobalAddress(cast<GlobalAddressSDNode>(" "GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
<< Val << ")->getGlobal(), MVT::" << getEnumName(N->getTypeNum(0)) ")->getGlobal(), MVT::" + getEnumName(N->getTypeNum(0)) +
<< ");\n"; ");");
} else } else {
OS << " SDOperand Tmp" << ResNo << " = " << Val << ";\n"; emitCode("SDOperand Tmp" + utostr(ResNo) + " = " + Val + ";");
}
} else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){ } else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
OS << " SDOperand Tmp" << ResNo << " = " << Val << ";\n"; emitCode("SDOperand Tmp" + utostr(ResNo) + " = " + Val + ";");
} else if (!N->isLeaf() && N->getOperator()->getName() == "tconstpool") { } else if (!N->isLeaf() && N->getOperator()->getName() == "tconstpool") {
OS << " SDOperand Tmp" << ResNo << " = " << Val << ";\n"; emitCode("SDOperand Tmp" + utostr(ResNo) + " = " + Val + ";");
} else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, ISE))) { } else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, ISE))) {
std::string Fn = CP->getSelectFunc(); std::string Fn = CP->getSelectFunc();
NumRes = CP->getNumOperands(); NumRes = CP->getNumOperands();
OS << " SDOperand "; std::string Code = "SDOperand ";
for (unsigned i = 0; i < NumRes - 1; ++i) for (unsigned i = 0; i < NumRes - 1; ++i)
OS << "Tmp" << (i+ResNo) << ","; Code += "Tmp" + utostr(i+ResNo) + ", ";
OS << "Tmp" << (NumRes - 1 + ResNo) << ";\n"; emitCode(Code + "Tmp" + utostr(NumRes - 1 + ResNo) + ";");
OS << " if (!" << Fn << "(" << Val; Code = "!" + Fn + "(" + Val;
for (unsigned i = 0; i < NumRes; i++) for (unsigned i = 0; i < NumRes; i++)
OS << ", Tmp" << i + ResNo; Code += ", Tmp" + utostr(i + ResNo);
OS << ")) goto P" << PatternNo << "Fail;\n"; emitCheck(Code + ")");
GotosFail = true;
TmpNo = ResNo + NumRes; TmpNo = ResNo + NumRes;
} else { } else {
OS << " SDOperand Tmp" << ResNo << " = Select(" << Val << ");\n"; emitCode("SDOperand Tmp" + utostr(ResNo) + " = Select(" + Val + ");");
} }
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select this // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
// value if used multiple times by this pattern result. // value if used multiple times by this pattern result.
@ -2156,19 +2136,17 @@ public:
if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) { if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
unsigned ResNo = TmpNo++; unsigned ResNo = TmpNo++;
if (DI->getDef()->isSubClassOf("Register")) { if (DI->getDef()->isSubClassOf("Register")) {
OS << " SDOperand Tmp" << ResNo << " = CurDAG->getRegister(" emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" +
<< ISE.getQualifiedName(DI->getDef()) << ", MVT::" ISE.getQualifiedName(DI->getDef()) + ", MVT::" +
<< getEnumName(N->getTypeNum(0)) getEnumName(N->getTypeNum(0)) + ");");
<< ");\n";
return std::make_pair(1, ResNo); return std::make_pair(1, ResNo);
} }
} else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { } else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
unsigned ResNo = TmpNo++; unsigned ResNo = TmpNo++;
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!"); assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
OS << " SDOperand Tmp" << ResNo << " = CurDAG->getTargetConstant(" emitCode("SDOperand Tmp" + utostr(ResNo) +
<< II->getValue() << ", MVT::" " = CurDAG->getTargetConstant(" + itostr(II->getValue()) +
<< getEnumName(N->getTypeNum(0)) ", MVT::" + getEnumName(N->getTypeNum(0)) + ");");
<< ");\n";
return std::make_pair(1, ResNo); return std::make_pair(1, ResNo);
} }
@ -2196,9 +2174,9 @@ public:
(isRoot && PatternHasProperty(Pattern, SDNodeInfo::SDNPHasChain, ISE)); (isRoot && PatternHasProperty(Pattern, SDNodeInfo::SDNPHasChain, ISE));
if (HasInFlag || NodeHasOutFlag || HasOptInFlag || HasImpInputs) if (HasInFlag || NodeHasOutFlag || HasOptInFlag || HasImpInputs)
OS << " SDOperand InFlag = SDOperand(0, 0);\n"; emitCode("SDOperand InFlag = SDOperand(0, 0);");
if (HasOptInFlag) if (HasOptInFlag)
OS << " bool HasOptInFlag = false;\n"; emitCode("bool HasOptInFlag = false;");
// How many results is this pattern expected to produce? // How many results is this pattern expected to produce?
unsigned NumExpectedResults = 0; unsigned NumExpectedResults = 0;
@ -2242,176 +2220,172 @@ public:
// Emit all the chain and CopyToReg stuff. // Emit all the chain and CopyToReg stuff.
bool ChainEmitted = HasChain; bool ChainEmitted = HasChain;
if (HasChain) if (HasChain)
OS << " Chain = Select(Chain);\n"; emitCode("Chain = Select(Chain);");
if (HasInFlag || HasOptInFlag || HasImpInputs) if (HasInFlag || HasOptInFlag || HasImpInputs)
EmitInFlagSelectCode(Pattern, "N", ChainEmitted, true); EmitInFlagSelectCode(Pattern, "N", ChainEmitted, true);
unsigned NumResults = Inst.getNumResults(); unsigned NumResults = Inst.getNumResults();
unsigned ResNo = TmpNo++; unsigned ResNo = TmpNo++;
if (!isRoot) { if (!isRoot) {
OS << " SDOperand Tmp" << ResNo << " = CurDAG->getTargetNode(" std::string Code =
<< II.Namespace << "::" << II.TheDef->getName(); "SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTargetNode(" +
II.Namespace + "::" + II.TheDef->getName();
if (N->getTypeNum(0) != MVT::isVoid) if (N->getTypeNum(0) != MVT::isVoid)
OS << ", MVT::" << getEnumName(N->getTypeNum(0)); Code += ", MVT::" + getEnumName(N->getTypeNum(0));
if (NodeHasOutFlag) if (NodeHasOutFlag)
OS << ", MVT::Flag"; Code += ", MVT::Flag";
unsigned LastOp = 0; unsigned LastOp = 0;
for (unsigned i = 0, e = Ops.size(); i != e; ++i) { for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
LastOp = Ops[i]; LastOp = Ops[i];
OS << ", Tmp" << LastOp; Code += ", Tmp" + utostr(LastOp);
} }
OS << ");\n"; emitCode(Code + ");");
if (HasChain) { if (HasChain) {
// Must have at least one result // Must have at least one result
OS << " Chain = Tmp" << LastOp << ".getValue(" emitCode("Chain = Tmp" + utostr(LastOp) + ".getValue(" +
<< NumResults << ");\n"; utostr(NumResults) + ");");
} }
} else if (HasChain || NodeHasOutFlag) { } else if (HasChain || NodeHasOutFlag) {
if (HasOptInFlag) { if (HasOptInFlag) {
OS << " SDOperand Result = SDOperand(0, 0);\n"; emitCode("SDOperand Result = SDOperand(0, 0);");
unsigned FlagNo = (unsigned) NodeHasChain + Pattern->getNumChildren(); unsigned FlagNo = (unsigned) NodeHasChain + Pattern->getNumChildren();
OS << " if (HasOptInFlag)\n"; emitCode("if (HasOptInFlag)");
OS << " Result = CurDAG->getTargetNode(" std::string Code = " Result = CurDAG->getTargetNode(" +
<< II.Namespace << "::" << II.TheDef->getName(); II.Namespace + "::" + II.TheDef->getName();
// Output order: results, chain, flags // Output order: results, chain, flags
// Result types. // Result types.
if (NumResults > 0) { if (NumResults > 0) {
if (N->getTypeNum(0) != MVT::isVoid) if (N->getTypeNum(0) != MVT::isVoid)
OS << ", MVT::" << getEnumName(N->getTypeNum(0)); Code += ", MVT::" + getEnumName(N->getTypeNum(0));
} }
if (HasChain) if (HasChain)
OS << ", MVT::Other"; Code += ", MVT::Other";
if (NodeHasOutFlag) if (NodeHasOutFlag)
OS << ", MVT::Flag"; Code += ", MVT::Flag";
// Inputs. // Inputs.
for (unsigned i = 0, e = Ops.size(); i != e; ++i) for (unsigned i = 0, e = Ops.size(); i != e; ++i)
OS << ", Tmp" << Ops[i]; Code += ", Tmp" + utostr(Ops[i]);
if (HasChain) OS << ", Chain"; if (HasChain) Code += ", Chain";
OS << ", InFlag);\n"; emitCode(Code + ", InFlag);");
OS << " else\n"; emitCode("else");
OS << " Result = CurDAG->getTargetNode(" Code = " Result = CurDAG->getTargetNode(" + II.Namespace + "::" +
<< II.Namespace << "::" << II.TheDef->getName(); II.TheDef->getName();
// Output order: results, chain, flags // Output order: results, chain, flags
// Result types. // Result types.
if (NumResults > 0) { if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid)
if (N->getTypeNum(0) != MVT::isVoid) Code += ", MVT::" + getEnumName(N->getTypeNum(0));
OS << ", MVT::" << getEnumName(N->getTypeNum(0));
}
if (HasChain) if (HasChain)
OS << ", MVT::Other"; Code += ", MVT::Other";
if (NodeHasOutFlag) if (NodeHasOutFlag)
OS << ", MVT::Flag"; Code += ", MVT::Flag";
// Inputs. // Inputs.
for (unsigned i = 0, e = Ops.size(); i != e; ++i) for (unsigned i = 0, e = Ops.size(); i != e; ++i)
OS << ", Tmp" << Ops[i]; Code += ", Tmp" + utostr(Ops[i]);
if (HasChain) OS << ", Chain);\n"; if (HasChain) Code += ", Chain);";
emitCode(Code);
} else { } else {
OS << " SDOperand Result = CurDAG->getTargetNode(" std::string Code = "SDOperand Result = CurDAG->getTargetNode(" +
<< II.Namespace << "::" << II.TheDef->getName(); II.Namespace + "::" + II.TheDef->getName();
// Output order: results, chain, flags // Output order: results, chain, flags
// Result types. // Result types.
if (NumResults > 0) { if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid)
if (N->getTypeNum(0) != MVT::isVoid) Code += ", MVT::" + getEnumName(N->getTypeNum(0));
OS << ", MVT::" << getEnumName(N->getTypeNum(0));
}
if (HasChain) if (HasChain)
OS << ", MVT::Other"; Code += ", MVT::Other";
if (NodeHasOutFlag) if (NodeHasOutFlag)
OS << ", MVT::Flag"; Code += ", MVT::Flag";
// Inputs. // Inputs.
for (unsigned i = 0, e = Ops.size(); i != e; ++i) for (unsigned i = 0, e = Ops.size(); i != e; ++i)
OS << ", Tmp" << Ops[i]; Code += ", Tmp" + utostr(Ops[i]);
if (HasChain) OS << ", Chain"; if (HasChain) Code += ", Chain";
if (HasInFlag || HasImpInputs) OS << ", InFlag"; if (HasInFlag || HasImpInputs) Code += ", InFlag";
OS << ");\n"; emitCode(Code + ");");
} }
unsigned ValNo = 0; unsigned ValNo = 0;
for (unsigned i = 0; i < NumResults; i++) { for (unsigned i = 0; i < NumResults; i++) {
OS << " CodeGenMap[N.getValue(" << ValNo << ")] = Result" emitCode("CodeGenMap[N.getValue(" + utostr(ValNo) + ")] = Result"
<< ".getValue(" << ValNo << ");\n"; ".getValue(" + utostr(ValNo) + ");");
ValNo++; ValNo++;
} }
if (HasChain) if (HasChain)
OS << " Chain = Result.getValue(" << ValNo << ");\n"; emitCode("Chain = Result.getValue(" + utostr(ValNo) + ");");
if (NodeHasOutFlag) if (NodeHasOutFlag)
OS << " InFlag = Result.getValue(" emitCode("InFlag = Result.getValue(" +
<< ValNo + (unsigned)HasChain << ");\n"; utostr(ValNo + (unsigned)HasChain) + ");");
if (HasImpResults) { if (HasImpResults && EmitCopyFromRegs(N, ChainEmitted)) {
if (EmitCopyFromRegs(N, ChainEmitted)) { emitCode("CodeGenMap[N.getValue(" + utostr(ValNo) + ")] = "
OS << " CodeGenMap[N.getValue(" << ValNo << ")] = " "Result.getValue(" + utostr(ValNo) + ");");
<< "Result.getValue(" << ValNo << ");\n"; ValNo++;
ValNo++;
}
} }
// User does not expect that the instruction produces a chain! // User does not expect that the instruction produces a chain!
bool AddedChain = HasChain && !NodeHasChain; bool AddedChain = HasChain && !NodeHasChain;
if (NodeHasChain) if (NodeHasChain)
OS << " CodeGenMap[N.getValue(" << ValNo++ << ")] = Chain;\n"; emitCode("CodeGenMap[N.getValue(" + utostr(ValNo++) + ")] = Chain;");
if (FoldedChains.size() > 0) { if (FoldedChains.size() > 0) {
OS << " "; std::string Code;
for (unsigned j = 0, e = FoldedChains.size(); j < e; j++) for (unsigned j = 0, e = FoldedChains.size(); j < e; j++)
OS << "CodeGenMap[" << FoldedChains[j].first << ".getValue(" Code += "CodeGenMap[" + FoldedChains[j].first + ".getValue(" +
<< FoldedChains[j].second << ")] = "; utostr(FoldedChains[j].second) + ")] = ";
OS << "Chain;\n"; emitCode(Code + "Chain;");
} }
if (NodeHasOutFlag) if (NodeHasOutFlag)
OS << " CodeGenMap[N.getValue(" << ValNo << ")] = InFlag;\n"; emitCode("CodeGenMap[N.getValue(" + utostr(ValNo) + ")] = InFlag;");
if (AddedChain && NodeHasOutFlag) { if (AddedChain && NodeHasOutFlag) {
if (NumExpectedResults == 0) { if (NumExpectedResults == 0) {
OS << " return Result.getValue(N.ResNo+1);\n"; emitCode("return Result.getValue(N.ResNo+1);");
} else { } else {
OS << " if (N.ResNo < " << NumExpectedResults << ")\n"; emitCode("if (N.ResNo < " + utostr(NumExpectedResults) + ")");
OS << " return Result.getValue(N.ResNo);\n"; emitCode(" return Result.getValue(N.ResNo);");
OS << " else\n"; emitCode("else");
OS << " return Result.getValue(N.ResNo+1);\n"; emitCode(" return Result.getValue(N.ResNo+1);");
} }
} else { } else {
OS << " return Result.getValue(N.ResNo);\n"; emitCode("return Result.getValue(N.ResNo);");
} }
} else { } else {
// If this instruction is the root, and if there is only one use of it, // If this instruction is the root, and if there is only one use of it,
// use SelectNodeTo instead of getTargetNode to avoid an allocation. // use SelectNodeTo instead of getTargetNode to avoid an allocation.
OS << " if (N.Val->hasOneUse()) {\n"; emitCode("if (N.Val->hasOneUse()) {");
OS << " return CurDAG->SelectNodeTo(N.Val, " std::string Code = " return CurDAG->SelectNodeTo(N.Val, " +
<< II.Namespace << "::" << II.TheDef->getName(); II.Namespace + "::" + II.TheDef->getName();
if (N->getTypeNum(0) != MVT::isVoid) if (N->getTypeNum(0) != MVT::isVoid)
OS << ", MVT::" << getEnumName(N->getTypeNum(0)); Code += ", MVT::" + getEnumName(N->getTypeNum(0));
if (NodeHasOutFlag) if (NodeHasOutFlag)
OS << ", MVT::Flag"; Code += ", MVT::Flag";
for (unsigned i = 0, e = Ops.size(); i != e; ++i) for (unsigned i = 0, e = Ops.size(); i != e; ++i)
OS << ", Tmp" << Ops[i]; Code += ", Tmp" + utostr(Ops[i]);
if (HasInFlag || HasImpInputs) if (HasInFlag || HasImpInputs)
OS << ", InFlag"; Code += ", InFlag";
OS << ");\n"; emitCode(Code + ");");
OS << " } else {\n"; emitCode("} else {");
OS << " return CodeGenMap[N] = CurDAG->getTargetNode(" Code = " return CodeGenMap[N] = CurDAG->getTargetNode(" +
<< II.Namespace << "::" << II.TheDef->getName(); II.Namespace + "::" + II.TheDef->getName();
if (N->getTypeNum(0) != MVT::isVoid) if (N->getTypeNum(0) != MVT::isVoid)
OS << ", MVT::" << getEnumName(N->getTypeNum(0)); Code += ", MVT::" + getEnumName(N->getTypeNum(0));
if (NodeHasOutFlag) if (NodeHasOutFlag)
OS << ", MVT::Flag"; Code += ", MVT::Flag";
for (unsigned i = 0, e = Ops.size(); i != e; ++i) for (unsigned i = 0, e = Ops.size(); i != e; ++i)
OS << ", Tmp" << Ops[i]; Code += ", Tmp" + utostr(Ops[i]);
if (HasInFlag || HasImpInputs) if (HasInFlag || HasImpInputs)
OS << ", InFlag"; Code += ", InFlag";
OS << ");\n"; emitCode(Code + ");");
OS << " }\n"; emitCode("}");
} }
return std::make_pair(1, ResNo); return std::make_pair(1, ResNo);
@ -2419,11 +2393,11 @@ public:
assert(N->getNumChildren() == 1 && "node xform should have one child!"); assert(N->getNumChildren() == 1 && "node xform should have one child!");
unsigned OpVal = EmitResultCode(N->getChild(0)).second; unsigned OpVal = EmitResultCode(N->getChild(0)).second;
unsigned ResNo = TmpNo++; unsigned ResNo = TmpNo++;
OS << " SDOperand Tmp" << ResNo << " = Transform_" << Op->getName() emitCode("SDOperand Tmp" + utostr(ResNo) + " = Transform_" + Op->getName()
<< "(Tmp" << OpVal << ".Val);\n"; + "(Tmp" + utostr(OpVal) + ".Val);");
if (isRoot) { if (isRoot) {
OS << " CodeGenMap[N] = Tmp" << ResNo << ";\n"; emitCode("CodeGenMap[N] = Tmp" +utostr(ResNo) + ";");
OS << " return Tmp" << ResNo << ";\n"; emitCode("return Tmp" + utostr(ResNo) + ";");
} }
return std::make_pair(1, ResNo); return std::make_pair(1, ResNo);
} else { } else {
@ -2443,9 +2417,8 @@ public:
if (!Pat->hasTypeSet()) { if (!Pat->hasTypeSet()) {
// Move a type over from 'other' to 'pat'. // Move a type over from 'other' to 'pat'.
Pat->setTypes(Other->getExtTypes()); Pat->setTypes(Other->getExtTypes());
OS << " if (" << Prefix << ".Val->getValueType(0) != MVT::" emitCheck(Prefix + ".Val->getValueType(0) != MVT::" +
<< getName(Pat->getTypeNum(0)) << ") goto P" << PatternNo << "Fail;\n"; getName(Pat->getTypeNum(0)));
GotosFail = true;
return true; return true;
} }
@ -2485,22 +2458,21 @@ private:
if (RR->isSubClassOf("Register")) { if (RR->isSubClassOf("Register")) {
MVT::ValueType RVT = getRegisterValueType(RR, T); MVT::ValueType RVT = getRegisterValueType(RR, T);
if (RVT == MVT::Flag) { if (RVT == MVT::Flag) {
OS << " InFlag = Select(" << RootName << OpNo << ");\n"; emitCode("InFlag = Select(" + RootName + utostr(OpNo) + ");");
} else { } else {
if (!ChainEmitted) { if (!ChainEmitted) {
OS << " SDOperand Chain = CurDAG->getEntryNode();\n"; emitCode("SDOperand Chain = CurDAG->getEntryNode();");
ChainEmitted = true; ChainEmitted = true;
} }
OS << " SDOperand " << RootName << "CR" << i << ";\n"; emitCode("SDOperand " + RootName + "CR" + utostr(i) + ";");
OS << " " << RootName << "CR" << i emitCode(RootName + "CR" + utostr(i) +
<< " = CurDAG->getCopyToReg(Chain, CurDAG->getRegister(" " = CurDAG->getCopyToReg(Chain, CurDAG->getRegister(" +
<< ISE.getQualifiedName(RR) << ", MVT::" ISE.getQualifiedName(RR) + ", MVT::" + getEnumName(RVT) +
<< getEnumName(RVT) << ")" "), Select(" + RootName + utostr(OpNo) + "), InFlag);");
<< ", Select(" << RootName << OpNo << "), InFlag);\n"; emitCode("Chain = " + RootName + "CR" + utostr(i) +
OS << " Chain = " << RootName << "CR" << i ".getValue(0);");
<< ".getValue(0);\n"; emitCode("InFlag = " + RootName + "CR" + utostr(i) +
OS << " InFlag = " << RootName << "CR" << i ".getValue(1);");
<< ".getValue(1);\n";
} }
} }
} }
@ -2508,16 +2480,17 @@ private:
} }
if (HasInFlag || HasOptInFlag) { if (HasInFlag || HasOptInFlag) {
std::string Code;
if (HasOptInFlag) { if (HasOptInFlag) {
OS << " if (" << RootName << ".getNumOperands() == " emitCode("if (" + RootName + ".getNumOperands() == " + utostr(OpNo+1) +
<< OpNo+1 << ") {\n"; ") {");
OS << " "; Code = " ";
} }
OS << " InFlag = Select(" << RootName << ".getOperand(" emitCode(Code + "InFlag = Select(" + RootName + ".getOperand(" +
<< OpNo << "));\n"; utostr(OpNo) + "));");
if (HasOptInFlag) { if (HasOptInFlag) {
OS << " HasOptInFlag = true;\n"; emitCode(" HasOptInFlag = true;");
OS << " }\n"; emitCode("}");
} }
} }
} }
@ -2539,14 +2512,14 @@ private:
MVT::ValueType RVT = getRegisterValueType(RR, CGT); MVT::ValueType RVT = getRegisterValueType(RR, CGT);
if (RVT != MVT::Flag) { if (RVT != MVT::Flag) {
if (!ChainEmitted) { if (!ChainEmitted) {
OS << " SDOperand Chain = CurDAG->getEntryNode();\n"; emitCode("SDOperand Chain = CurDAG->getEntryNode();");
ChainEmitted = true; ChainEmitted = true;
} }
OS << " Result = CurDAG->getCopyFromReg(Chain, " emitCode("Result = CurDAG->getCopyFromReg(Chain, " +
<< ISE.getQualifiedName(RR) ISE.getQualifiedName(RR) + ", MVT::" + getEnumName(RVT) +
<< ", MVT::" << getEnumName(RVT) << ", InFlag);\n"; ", InFlag);");
OS << " Chain = Result.getValue(1);\n"; emitCode("Chain = Result.getValue(1);");
OS << " InFlag = Result.getValue(2);\n"; emitCode("InFlag = Result.getValue(2);");
RetVal = true; RetVal = true;
} }
} }
@ -2564,19 +2537,11 @@ bool DAGISelEmitter::EmitCodeForPattern(PatternToMatch &Pattern,
std::ostream &OS) { std::ostream &OS) {
static unsigned PatternCount = 0; static unsigned PatternCount = 0;
unsigned PatternNo = PatternCount++; unsigned PatternNo = PatternCount++;
OS << " { // Pattern #" << PatternNo << ": ";
Pattern.getSrcPattern()->print(OS);
OS << "\n // Emits: ";
Pattern.getDstPattern()->print(OS);
OS << "\n";
OS << " // Pattern complexity = "
<< getPatternSize(Pattern.getSrcPattern(), *this)
<< " cost = "
<< getResultPatternCost(Pattern.getDstPattern()) << "\n";
std::vector<std::pair<bool, std::string> > GeneratedCode;
PatternCodeEmitter Emitter(*this, Pattern.getPredicates(), PatternCodeEmitter Emitter(*this, Pattern.getPredicates(),
Pattern.getSrcPattern(), Pattern.getDstPattern(), Pattern.getSrcPattern(), Pattern.getDstPattern(),
PatternNo, OS); PatternNo, GeneratedCode);
// Emit the matcher, capturing named arguments in VariableMap. // Emit the matcher, capturing named arguments in VariableMap.
bool FoundChain = false; bool FoundChain = false;
@ -2623,12 +2588,35 @@ bool DAGISelEmitter::EmitCodeForPattern(PatternToMatch &Pattern,
delete Pat; delete Pat;
if (Emitter.UsesFailLabel())
OS << " }\n P" << PatternNo << "Fail:\n"; OS << " { // Pattern #" << PatternNo << ": ";
else Pattern.getSrcPattern()->print(OS);
OS << " }\n"; OS << "\n // Emits: ";
Pattern.getDstPattern()->print(OS);
OS << "\n";
OS << " // Pattern complexity = "
<< getPatternSize(Pattern.getSrcPattern(), *this)
<< " cost = "
<< getResultPatternCost(Pattern.getDstPattern()) << "\n";
// Actually output the generated code now.
bool CanFail = false;
for (unsigned i = 0, e = GeneratedCode.size(); i != e; ++i) {
if (!GeneratedCode[i].first) {
// Normal code.
OS << " " << GeneratedCode[i].second << "\n";
} else {
OS << " if (" << GeneratedCode[i].second << ") goto P"
<< PatternNo << "Fail;\n";
CanFail = true;
}
}
OS << " }\n";
if (CanFail)
OS << "P" << PatternNo << "Fail:\n";
return Emitter.UsesFailLabel(); return CanFail;
} }