std::map<std::string, std::string> VariableMap;
// Node to operator mapping
std::map<std::string, Record*> OperatorMap;
+ // Name of the folded node which produces a flag.
+ std::pair<std::string, unsigned> FoldedFlag;
// Names of all the folded nodes which produce chains.
std::vector<std::pair<std::string, unsigned> > FoldedChains;
// Original input chain(s).
emitCheck(MaskPredicate + RootName + "0, cast<ConstantSDNode>(" +
RootName + "1), " + itostr(II->getValue()) + ")");
- EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0),
+ EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0), RootName,
ChainSuffix + utostr(0), FoundChain);
return;
}
emitInit("SDOperand " + RootName + utostr(OpNo) + " = " +
RootName + ".getOperand(" +utostr(OpNo) + ");");
- EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo),
+ EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo), RootName,
ChainSuffix + utostr(OpNo), FoundChain);
}
}
void EmitChildMatchCode(TreePatternNode *Child, TreePatternNode *Parent,
- const std::string &RootName,
+ const std::string &RootName,
+ const std::string &ParentRootName,
const std::string &ChainSuffix, bool &FoundChain) {
if (!Child->isLeaf()) {
// If it's not a leaf, recursively match.
emitCheck(RootName + ".getOpcode() == " +
CInfo.getEnumName());
EmitMatchCode(Child, Parent, RootName, ChainSuffix, FoundChain);
- if (NodeHasProperty(Child, SDNPHasChain, CGP))
+ bool HasChain = false;
+ if (NodeHasProperty(Child, SDNPHasChain, CGP)) {
+ HasChain = true;
FoldedChains.push_back(std::make_pair(RootName, CInfo.getNumResults()));
+ }
+ if (NodeHasProperty(Child, SDNPOutFlag, CGP)) {
+ assert(FoldedFlag.first == "" && FoldedFlag.second == 0 &&
+ "Pattern folded multiple nodes which produce flags?");
+ FoldedFlag = std::make_pair(RootName,
+ CInfo.getNumResults() + (unsigned)HasChain);
+ }
} else {
// 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.
emitCode("SDOperand " + ChainName + ";");
}
- std::string Code = Fn + "(N, ";
+ std::string Code = Fn + "(";
+ if (CP->hasAttribute(CPAttrParentAsRoot)) {
+ Code += ParentRootName + ", ";
+ } else {
+ Code += "N, ";
+ }
if (CP->hasProperty(SDNPHasChain)) {
std::string ParentName(RootName.begin(), RootName.end()-1);
Code += ParentName + ", ";
std::vector<std::string> NodeOps;
// This is something selected from the pattern we matched.
if (!N->getName().empty()) {
- std::string &Val = VariableMap[N->getName()];
+ const std::string &VarName = N->getName();
+ std::string Val = VariableMap[VarName];
+ bool ModifiedVal = false;
assert(!Val.empty() &&
"Variable referenced but not defined and not caught earlier!");
if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') {
if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
std::string CastType;
+ std::string TmpVar = "Tmp" + utostr(ResNo);
switch (N->getTypeNum(0)) {
default:
cerr << "Cannot handle " << getEnumName(N->getTypeNum(0))
case MVT::i32: CastType = "unsigned"; break;
case MVT::i64: CastType = "uint64_t"; break;
}
- emitCode("SDOperand Tmp" + utostr(ResNo) +
+ emitCode("SDOperand " + TmpVar +
" = CurDAG->getTargetConstant(((" + CastType +
") cast<ConstantSDNode>(" + Val + ")->getValue()), " +
getEnumName(N->getTypeNum(0)) + ");");
- NodeOps.push_back("Tmp" + utostr(ResNo));
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
// value if used multiple times by this pattern result.
- Val = "Tmp"+utostr(ResNo);
+ Val = TmpVar;
+ ModifiedVal = true;
+ NodeOps.push_back(Val);
} else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
Record *Op = OperatorMap[N->getName()];
// Transform ExternalSymbol to TargetExternalSymbol
if (Op && Op->getName() == "externalsym") {
- emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
+ std::string TmpVar = "Tmp"+utostr(ResNo);
+ emitCode("SDOperand " + TmpVar + " = CurDAG->getTarget"
"ExternalSymbol(cast<ExternalSymbolSDNode>(" +
Val + ")->getSymbol(), " +
getEnumName(N->getTypeNum(0)) + ");");
- NodeOps.push_back("Tmp" + utostr(ResNo));
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select
// this value if used multiple times by this pattern result.
- Val = "Tmp"+utostr(ResNo);
- } else {
- NodeOps.push_back(Val);
+ Val = TmpVar;
+ ModifiedVal = true;
}
+ NodeOps.push_back(Val);
} else if (!N->isLeaf() && (N->getOperator()->getName() == "tglobaladdr"
|| N->getOperator()->getName() == "tglobaltlsaddr")) {
Record *Op = OperatorMap[N->getName()];
// Transform GlobalAddress to TargetGlobalAddress
if (Op && (Op->getName() == "globaladdr" ||
Op->getName() == "globaltlsaddr")) {
- emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
+ std::string TmpVar = "Tmp" + utostr(ResNo);
+ emitCode("SDOperand " + TmpVar + " = CurDAG->getTarget"
"GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
");");
- NodeOps.push_back("Tmp" + utostr(ResNo));
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select
// this value if used multiple times by this pattern result.
- Val = "Tmp"+utostr(ResNo);
- } else {
- NodeOps.push_back(Val);
+ Val = TmpVar;
+ ModifiedVal = true;
}
- } else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
NodeOps.push_back(Val);
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
- // value if used multiple times by this pattern result.
- Val = "Tmp"+utostr(ResNo);
- } else if (!N->isLeaf() && N->getOperator()->getName() == "tconstpool") {
+ } else if (!N->isLeaf()
+ && (N->getOperator()->getName() == "texternalsym"
+ || N->getOperator()->getName() == "tconstpool")) {
+ // Do not rewrite the variable name, since we don't generate a new
+ // temporary.
NodeOps.push_back(Val);
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
- // value if used multiple times by this pattern result.
- Val = "Tmp"+utostr(ResNo);
} else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, CGP))) {
for (unsigned i = 0; i < CP->getNumOperands(); ++i) {
emitCode("AddToISelQueue(CPTmp" + utostr(i) + ");");
}
NodeOps.push_back(Val);
}
+
+ if (ModifiedVal) {
+ VariableMap[VarName] = Val;
+ }
return NodeOps;
}
if (N->isLeaf()) {
const CodeGenTarget &CGT = CGP.getTargetInfo();
CodeGenInstruction &II = CGT.getInstruction(Op->getName());
const DAGInstruction &Inst = CGP.getInstruction(Op);
- TreePattern *InstPat = Inst.getPattern();
+ const TreePattern *InstPat = Inst.getPattern();
// FIXME: Assume actual pattern comes before "implicit".
TreePatternNode *InstPatNode =
isRoot ? (InstPat ? InstPat->getTree(0) : Pattern)
if (InstPatNode && InstPatNode->getOperator()->getName() == "set") {
InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
}
- bool HasVarOps = isRoot && II.hasVariableNumberOfOperands;
+ bool HasVarOps = isRoot && II.isVariadic;
// FIXME: fix how we deal with physical register operands.
bool HasImpInputs = isRoot && Inst.getNumImpOperands() > 0;
bool HasImpResults = isRoot && DstRegs.size() > 0;
}
if (NodeHasOutFlag) {
- emitCode("ReplaceUses(SDOperand(N.Val, " +
- utostr(NumPatResults + (unsigned)InputHasChain)
- +"), InFlag);");
+ if (FoldedFlag.first != "") {
+ emitCode("ReplaceUses(SDOperand(" + FoldedFlag.first + ".Val, " +
+ utostr(FoldedFlag.second) + "), InFlag);");
+ } else {
+ assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
+ emitCode("ReplaceUses(SDOperand(N.Val, " +
+ utostr(NumPatResults + (unsigned)InputHasChain)
+ +"), InFlag);");
+ }
NeedReplace = true;
}
OS << "SDNode *Select_LABEL(const SDOperand &N) {\n"
<< " SDOperand Chain = N.getOperand(0);\n"
<< " SDOperand N1 = N.getOperand(1);\n"
- << " unsigned C = cast<ConstantSDNode>(N1)->getValue();\n"
- << " SDOperand Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
+ << " SDOperand N2 = N.getOperand(2);\n"
+ << " unsigned C1 = cast<ConstantSDNode>(N1)->getValue();\n"
+ << " unsigned C2 = cast<ConstantSDNode>(N2)->getValue();\n"
+ << " SDOperand Tmp1 = CurDAG->getTargetConstant(C1, MVT::i32);\n"
+ << " SDOperand Tmp2 = CurDAG->getTargetConstant(C2, MVT::i32);\n"
<< " AddToISelQueue(Chain);\n"
- << " SDOperand Ops[] = { Tmp, Chain };\n"
+ << " SDOperand Ops[] = { Tmp1, Tmp2, Chain };\n"
<< " return CurDAG->getTargetNode(TargetInstrInfo::LABEL,\n"
- << " MVT::Other, Ops, 2);\n"
+ << " MVT::Other, Ops, 3);\n"
+ << "}\n\n";
+
+ OS << "SDNode *Select_DECLARE(const SDOperand &N) {\n"
+ << " SDOperand Chain = N.getOperand(0);\n"
+ << " SDOperand N1 = N.getOperand(1);\n"
+ << " SDOperand N2 = N.getOperand(2);\n"
+ << " if (!isa<FrameIndexSDNode>(N1) || !isa<GlobalAddressSDNode>(N2)) {\n"
+ << " cerr << \"Cannot yet select llvm.dbg.declare: \";\n"
+ << " N.Val->dump(CurDAG);\n"
+ << " abort();\n"
+ << " }\n"
+ << " int FI = cast<FrameIndexSDNode>(N1)->getIndex();\n"
+ << " GlobalValue *GV = cast<GlobalAddressSDNode>(N2)->getGlobal();\n"
+ << " SDOperand Tmp1 = "
+ << "CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());\n"
+ << " SDOperand Tmp2 = "
+ << "CurDAG->getTargetGlobalAddress(GV, TLI.getPointerTy());\n"
+ << " AddToISelQueue(Chain);\n"
+ << " SDOperand Ops[] = { Tmp1, Tmp2, Chain };\n"
+ << " return CurDAG->getTargetNode(TargetInstrInfo::DECLARE,\n"
+ << " MVT::Other, Ops, 3);\n"
<< "}\n\n";
OS << "SDNode *Select_EXTRACT_SUBREG(const SDOperand &N) {\n"
<< " }\n"
<< " case ISD::INLINEASM: return Select_INLINEASM(N);\n"
<< " case ISD::LABEL: return Select_LABEL(N);\n"
+ << " case ISD::DECLARE: return Select_DECLARE(N);\n"
<< " case ISD::EXTRACT_SUBREG: return Select_EXTRACT_SUBREG(N);\n"
<< " case ISD::INSERT_SUBREG: return Select_INSERT_SUBREG(N);\n";
<< "// *** instruction selector class. These functions are really "
<< "methods.\n\n";
- OS << "#include \"llvm/Support/Compiler.h\"\n";
-
OS << "// Instruction selector priority queue:\n"
<< "std::vector<SDNode*> ISelQueue;\n";
OS << "/// Keep track of nodes which have already been added to queue.\n"
<< "unsigned char *ISelQueued;\n";
OS << "/// Keep track of nodes which have already been selected.\n"
<< "unsigned char *ISelSelected;\n";
- OS << "/// Dummy parameter to ReplaceAllUsesOfValueWith().\n"
- << "std::vector<SDNode*> ISelKilled;\n\n";
+
OS << "/// IsChainCompatible - Returns true if Chain is Op or Chain does\n";
OS << "/// not reach Op.\n";
OS << " }\n";
OS << "}\n\n";
- OS << "inline void RemoveKilled() {\n";
-OS << " unsigned NumKilled = ISelKilled.size();\n";
- OS << " if (NumKilled) {\n";
- OS << " for (unsigned i = 0; i != NumKilled; ++i) {\n";
- OS << " SDNode *Temp = ISelKilled[i];\n";
- OS << " ISelQueue.erase(std::remove(ISelQueue.begin(), ISelQueue.end(), "
- << "Temp), ISelQueue.end());\n";
- OS << " };\n";
- OS << " std::make_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());\n";
- OS << " ISelKilled.clear();\n";
- OS << " }\n";
+
+ OS << "class VISIBILITY_HIDDEN ISelQueueUpdater :\n";
+ OS << " public SelectionDAG::DAGUpdateListener {\n";
+ OS << " std::vector<SDNode*> &ISelQueue;\n";
+ OS << " bool HadDelete;\n";
+ OS << " public:\n";
+ OS << " ISelQueueUpdater(std::vector<SDNode*> &isq)\n";
+ OS << " : ISelQueue(isq), HadDelete(false) {}\n";
+ OS << " \n";
+ OS << " bool hadDelete() const { return HadDelete; }\n";
+ OS << " \n";
+ OS << " virtual void NodeDeleted(SDNode *N) {\n";
+ OS << " ISelQueue.erase(std::remove(ISelQueue.begin(), ISelQueue.end(),";
+ OS << " N),\n ISelQueue.end());\n";
+ OS << " HadDelete = true;\n";
+ OS << " }\n";
+ OS << " \n";
+ OS << " // Ignore updates.\n";
+ OS << " virtual void NodeUpdated(SDNode *N) {}\n";
+ OS << " };\n";
+
+ OS << "inline void UpdateQueue(const ISelQueueUpdater &ISQU) {\n";
+ OS << " if (ISQU.hadDelete())\n";
+ OS << " std::make_heap(ISelQueue.begin(), ISelQueue.end(),isel_sort());\n";
OS << "}\n\n";
OS << "void ReplaceUses(SDOperand F, SDOperand T) DISABLE_INLINE {\n";
- OS << " CurDAG->ReplaceAllUsesOfValueWith(F, T, &ISelKilled);\n";
+ OS << " ISelQueueUpdater ISQU(ISelQueue);\n";
+ OS << " CurDAG->ReplaceAllUsesOfValueWith(F, T, &ISQU);\n";
OS << " setSelected(F.Val->getNodeId());\n";
- OS << " RemoveKilled();\n";
+ OS << " UpdateQueue(ISQU);\n";
OS << "}\n";
OS << "void ReplaceUses(SDNode *F, SDNode *T) DISABLE_INLINE {\n";
OS << " unsigned FNumVals = F->getNumValues();\n";
OS << " unsigned TNumVals = T->getNumValues();\n";
+ OS << " ISelQueueUpdater ISQU(ISelQueue);\n";
OS << " if (FNumVals != TNumVals) {\n";
OS << " for (unsigned i = 0, e = std::min(FNumVals, TNumVals); "
<< "i < e; ++i)\n";
OS << " CurDAG->ReplaceAllUsesOfValueWith(SDOperand(F, i), "
- << "SDOperand(T, i), &ISelKilled);\n";
+ << "SDOperand(T, i), &ISQU);\n";
OS << " } else {\n";
- OS << " CurDAG->ReplaceAllUsesWith(F, T, &ISelKilled);\n";
+ OS << " CurDAG->ReplaceAllUsesWith(F, T, &ISQU);\n";
OS << " }\n";
OS << " setSelected(F->getNodeId());\n";
- OS << " RemoveKilled();\n";
+ OS << " UpdateQueue(ISQU);\n";
OS << "}\n\n";
OS << "// SelectRoot - Top level entry to DAG isel.\n";
OS << " if (ResNode)\n";
OS << " ReplaceUses(Node, ResNode);\n";
OS << " if (Node->use_empty()) { // Don't delete EntryToken, etc.\n";
- OS << " CurDAG->RemoveDeadNode(Node, ISelKilled);\n";
- OS << " RemoveKilled();\n";
+ OS << " ISelQueueUpdater ISQU(ISelQueue);\n";
+ OS << " CurDAG->RemoveDeadNode(Node, &ISQU);\n";
+ OS << " UpdateQueue(ISQU);\n";
OS << " }\n";
OS << " }\n";
OS << " }\n";