/// GeneratedDecl - This is the set of all SDOperand declarations needed for
/// the set of patterns for each top-level opcode.
std::set<std::pair<bool, std::string> > &GeneratedDecl;
+ /// TargetOpcodes - The target specific opcodes used by the resulting
+ /// instructions.
+ std::vector<std::string> &TargetOpcodes;
std::string ChainName;
bool NewTF;
bool DoReplace;
unsigned TmpNo;
+ unsigned OpcNo;
void emitCheck(const std::string &S) {
if (!S.empty())
assert(!S.empty() && "Invalid declaration");
GeneratedDecl.insert(std::make_pair(isSDNode, S));
}
+ void emitOpcode(const std::string &Opc) {
+ TargetOpcodes.push_back(Opc);
+ OpcNo++;
+ }
public:
PatternCodeEmitter(DAGISelEmitter &ise, ListInit *preds,
TreePatternNode *pattern, TreePatternNode *instr,
std::vector<std::pair<bool, std::string> > &gc,
std::set<std::pair<bool, std::string> > &gd,
+ std::vector<std::string> &to,
bool dorep)
: ISE(ise), Predicates(preds), Pattern(pattern), Instruction(instr),
- GeneratedCode(gc), GeneratedDecl(gd),
- NewTF(false), DoReplace(dorep), TmpNo(0) {}
+ GeneratedCode(gc), GeneratedDecl(gd), TargetOpcodes(to),
+ NewTF(false), DoReplace(dorep), TmpNo(0), OpcNo(0) {}
/// 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
case MVT::i32: CastType = "unsigned"; break;
case MVT::i64: CastType = "uint64_t"; break;
}
- emitCode(CastType + " Tmp" + utostr(ResNo) + "C = (" + CastType +
- ")cast<ConstantSDNode>(" + Val + ")->getValue();");
emitDecl("Tmp" + utostr(ResNo));
emitCode("Tmp" + utostr(ResNo) +
- " = CurDAG->getTargetConstant(Tmp" + utostr(ResNo) +
- "C, " + getEnumName(N->getTypeNum(0)) + ");");
+ " = CurDAG->getTargetConstant(((" + CastType +
+ ") cast<ConstantSDNode>(" + Val + ")->getValue()), " +
+ getEnumName(N->getTypeNum(0)) + ");");
} else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
Record *Op = OperatorMap[N->getName()];
// Transform ExternalSymbol to TargetExternalSymbol
if (NodeHasInFlag || NodeHasOutFlag || NodeHasOptInFlag || HasImpInputs)
emitDecl("InFlag");
- if (NodeHasOptInFlag)
- emitCode("bool HasInFlag = "
- "N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag;");
+ if (NodeHasOptInFlag) {
+ // FIXME: This is ugly. We are using a SDNode* in place of a bool.
+ emitDecl("HasInFlag", true);
+ emitCode("HasInFlag = "
+ "(N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag) "
+ "? (SDNode*)1 : (SDNode*)0;");
+ }
if (HasVarOps)
emitCode("std::vector<SDOperand> Ops;");
emitDecl(NodeName, true);
Code2 = NodeName + " = ";
}
- Code = "CurDAG->getTargetNode(" +
- II.Namespace + "::" + II.TheDef->getName();
+ Code = "CurDAG->getTargetNode(Opc" + utostr(OpcNo);
+ emitOpcode(II.Namespace + "::" + II.TheDef->getName());
// Output order: results, chain, flags
// Result types.
emitCode("for (unsigned i = 2, e = N.getNumOperands()-1; "
"i != e; ++i) {");
else if (NodeHasOptInFlag)
- emitCode("for (unsigned i = 2, e = N.getNumOperands()-HasInFlag; "
- "i != e; ++i) {");
+ emitCode("for (unsigned i = 2, e = N.getNumOperands()-"
+ "(HasInFlag?1:0); i != e; ++i) {");
else
emitCode("for (unsigned i = 2, e = N.getNumOperands(); "
"i != e; ++i) {");
// If this instruction is the root, and if there is only one use of it,
// use SelectNodeTo instead of getTargetNode to avoid an allocation.
emitCode("if (N.Val->hasOneUse()) {");
- std::string Code = " Result = CurDAG->SelectNodeTo(N.Val, " +
- II.Namespace + "::" + II.TheDef->getName();
+ std::string Code = " Result = CurDAG->SelectNodeTo(N.Val, Opc" +
+ utostr(OpcNo);
if (N->getTypeNum(0) != MVT::isVoid)
Code += ", " + getEnumName(N->getTypeNum(0));
if (NodeHasOutFlag)
emitCode(Code + ");");
emitCode("} else {");
emitDecl("ResNode", true);
- Code = " ResNode = CurDAG->getTargetNode(" +
- II.Namespace + "::" + II.TheDef->getName();
+ Code = " ResNode = CurDAG->getTargetNode(Opc" + utostr(OpcNo);
+ emitOpcode(II.Namespace + "::" + II.TheDef->getName());
if (N->getTypeNum(0) != MVT::isVoid)
Code += ", " + getEnumName(N->getTypeNum(0));
if (NodeHasOutFlag)
ChainEmitted = true;
ChainName = "Chain";
}
- emitCode("ResNode = CurDAG->getCopyFromReg(" + ChainName + ", " +
- ISE.getQualifiedName(RR) + ", " + getEnumName(RVT) +
+ emitCode("ResNode = CurDAG->getCopyFromReg(" + ChainName +
+ ", " + ISE.getQualifiedName(RR) + ", " + getEnumName(RVT) +
", InFlag).Val;");
emitCode(ChainName + " = SDOperand(ResNode, 1);");
emitCode("InFlag = SDOperand(ResNode, 2);");
void DAGISelEmitter::GenerateCodeForPattern(PatternToMatch &Pattern,
std::vector<std::pair<bool, std::string> > &GeneratedCode,
std::set<std::pair<bool, std::string> > &GeneratedDecl,
+ std::vector<std::string> &TargetOpcodes,
bool DoReplace) {
PatternCodeEmitter Emitter(*this, Pattern.getPredicates(),
Pattern.getSrcPattern(), Pattern.getDstPattern(),
- GeneratedCode, GeneratedDecl, DoReplace);
+ GeneratedCode, GeneratedDecl, TargetOpcodes,
+ DoReplace);
// Emit the matcher, capturing named arguments in VariableMap.
bool FoundChain = false;
// Group the patterns by their top-level opcodes.
std::map<Record*, std::vector<PatternToMatch*>,
CompareByRecordName> PatternsByOpcode;
+ // All unique target node emission functions.
+ std::map<std::string, unsigned> EmitFunctions;
for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
TreePatternNode *Node = PatternsToMatch[i].getSrcPattern();
if (!Node->isLeaf()) {
CompareByRecordName>::iterator PBOI = PatternsByOpcode.begin(),
E = PatternsByOpcode.end(); PBOI != E; ++PBOI) {
const std::string &OpName = PBOI->first->getName();
- OS << "void Select_" << OpName << "(SDOperand &Result, SDOperand N) {\n";
-
const SDNodeInfo &OpcodeInfo = getSDNodeInfo(PBOI->first);
bool OptSlctOrder =
(OpcodeInfo.hasProperty(SDNodeInfo::SDNPHasChain) &&
OpcodeInfo.getNumResults() > 0);
-
- if (OptSlctOrder) {
- OS << " if (N.ResNo == " << OpcodeInfo.getNumResults()
- << " && N.getValue(0).hasOneUse()) {\n"
- << " SDOperand Dummy = "
- << "CurDAG->getNode(ISD::HANDLENODE, MVT::Other, N);\n"
- << " SelectionDAG::InsertISelMapEntry(CodeGenMap, N.Val, "
- << OpcodeInfo.getNumResults() << ", Dummy.Val, 0);\n"
- << " SelectionDAG::InsertISelMapEntry(HandleMap, N.Val, "
- << OpcodeInfo.getNumResults() << ", Dummy.Val, 0);\n"
- << " Result = Dummy;\n"
- << " return;\n"
- << " }\n";
- }
-
std::vector<PatternToMatch*> &Patterns = PBOI->second;
assert(!Patterns.empty() && "No patterns but map has entry?");
PatternSortingPredicate(*this));
typedef std::vector<std::pair<bool, std::string> > CodeList;
- typedef std::set<std::string> DeclSet;
+ typedef std::vector<std::pair<bool, std::string> >::iterator CodeListI;
std::vector<std::pair<PatternToMatch*, CodeList> > CodeForPatterns;
- std::set<std::pair<bool, std::string> > GeneratedDecl;
+ std::vector<std::vector<std::string> > PatternOpcodes;
+ std::vector<std::set<std::pair<bool, std::string> > > PatternDecls;
+ std::set<std::pair<bool, std::string> > AllGenDecls;
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
CodeList GeneratedCode;
+ std::set<std::pair<bool, std::string> > GeneratedDecl;
+ std::vector<std::string> TargetOpcodes;
GenerateCodeForPattern(*Patterns[i], GeneratedCode, GeneratedDecl,
- OptSlctOrder);
+ TargetOpcodes, OptSlctOrder);
+ for (std::set<std::pair<bool, std::string> >::iterator
+ si = GeneratedDecl.begin(), se = GeneratedDecl.end(); si!=se; ++si)
+ AllGenDecls.insert(*si);
CodeForPatterns.push_back(std::make_pair(Patterns[i], GeneratedCode));
+ PatternDecls.push_back(GeneratedDecl);
+ PatternOpcodes.push_back(TargetOpcodes);
}
// Scan the code to see if all of the patterns are reachable and if it is
}
}
+ // Factor target node emission code (emitted by EmitResultCode) into
+ // separate functions. Uniquing and share them among all instruction
+ // selection routines.
+ for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
+ CodeList &GeneratedCode = CodeForPatterns[i].second;
+ std::vector<std::string> &TargetOpcodes = PatternOpcodes[i];
+ std::set<std::pair<bool, std::string> > Decls = PatternDecls[i];
+ int CodeSize = (int)GeneratedCode.size();
+ int LastPred = -1;
+ for (int j = CodeSize-1; j >= 0; --j) {
+ if (GeneratedCode[j].first) {
+ LastPred = j;
+ break;
+ }
+ }
+
+ std::string CalleeDecls;
+ std::string CalleeCode = "(SDOperand &Result, SDOperand &N";
+ std::string CallerCode = "(Result, N";
+ for (unsigned j = 0, e = TargetOpcodes.size(); j != e; ++j) {
+ CalleeCode += ", unsigned Opc" + utostr(j);
+ CallerCode += ", " + TargetOpcodes[j];
+ }
+ for (std::set<std::pair<bool, std::string> >::iterator
+ I = Decls.begin(), E = Decls.end(); I != E; ++I) {
+ std::string Name = I->second;
+ if (I->first) {
+ CalleeCode += ", SDNode *" + Name;
+ CallerCode += ", " + Name;
+ } else {
+ CalleeCode += ", SDOperand &" + Name;
+ CallerCode += ", " + Name;
+ }
+ }
+ CallerCode += ");";
+ CalleeCode += ") ";
+#ifndef _MSC_VER
+ // Prevent emission routines from being inlined to reduce selection
+ // routines stack frame sizes.
+ CalleeCode += "__attribute__((noinline)) ";
+#endif
+ CalleeCode += "{\n" + CalleeDecls;
+ for (int j = LastPred+1; j < CodeSize; ++j)
+ CalleeCode += " " + GeneratedCode[j].second + '\n';
+ for (int j = LastPred+1; j < CodeSize; ++j)
+ GeneratedCode.pop_back();
+ CalleeCode += "}\n";
+
+ // Uniquing the emission routines.
+ unsigned EmitFuncNum;
+ std::map<std::string, unsigned>::iterator EFI =
+ EmitFunctions.find(CalleeCode);
+ if (EFI != EmitFunctions.end()) {
+ EmitFuncNum = EFI->second;
+ } else {
+ EmitFuncNum = EmitFunctions.size();
+ EmitFunctions.insert(std::make_pair(CalleeCode, EmitFuncNum));
+ OS << "void " << "Emit_" << utostr(EmitFuncNum) << CalleeCode;
+ }
+
+ // Replace the emission code within selection routines with calls to the
+ // emission functions.
+ CallerCode = "Emit_" + utostr(EmitFuncNum) + CallerCode;
+ GeneratedCode.push_back(std::make_pair(false, CallerCode));
+ GeneratedCode.push_back(std::make_pair(false, "return;"));
+ }
+
+ // Print function.
+ OS << "void Select_" << OpName << "(SDOperand &Result, SDOperand N) {\n";
+ if (OptSlctOrder) {
+ OS << " if (N.ResNo == " << OpcodeInfo.getNumResults()
+ << " && N.getValue(0).hasOneUse()) {\n"
+ << " SDOperand Dummy = "
+ << "CurDAG->getNode(ISD::HANDLENODE, MVT::Other, N);\n"
+ << " SelectionDAG::InsertISelMapEntry(CodeGenMap, N.Val, "
+ << OpcodeInfo.getNumResults() << ", Dummy.Val, 0);\n"
+ << " SelectionDAG::InsertISelMapEntry(HandleMap, N.Val, "
+ << OpcodeInfo.getNumResults() << ", Dummy.Val, 0);\n"
+ << " Result = Dummy;\n"
+ << " return;\n"
+ << " }\n";
+ }
+
// Print all declarations.
for (std::set<std::pair<bool, std::string> >::iterator
- I = GeneratedDecl.begin(), E = GeneratedDecl.end(); I != E; ++I)
+ I = AllGenDecls.begin(), E = AllGenDecls.end(); I != E; ++I)
if (I->first)
- OS << " SDNode *" << I->second << ";\n";
+ OS << " SDNode *" << I->second << " = NULL;\n";
else
OS << " SDOperand " << I->second << "(0, 0);\n";