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).
std::vector<std::pair<std::string, std::string> > OrigChains;
std::set<std::string> Duplicates;
- /// LSI - Load/Store information.
- /// Save loads/stores matched by a pattern, and generate a MemOperandSDNode
- /// for each memory access. This facilitates the use of AliasAnalysis in
- /// the backend.
- std::vector<std::string> LSI;
-
/// GeneratedCode - This is the buffer that we emit code to. The first int
/// indicates whether this is an exit predicate (something that should be
/// tested, and if true, the match fails) [when 1], or normal code to emit
void EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
const std::string &RootName, const std::string &ChainSuffix,
bool &FoundChain) {
-
- // Save loads/stores matched by a pattern.
- if (!N->isLeaf() && N->getName().empty() &&
- ((N->getOperator()->getName() == "ld") ||
- (N->getOperator()->getName() == "st") ||
- (N->getOperator()->getName() == "ist"))) {
- LSI.push_back(RootName);
- }
-
bool isRoot = (P == NULL);
// Emit instruction predicates. Each predicate is just a string for now.
if (isRoot) {
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.
}
}
- // Generate MemOperandSDNodes nodes for each memory accesses covered by this
- // pattern.
- if (isRoot) {
- std::vector<std::string>::const_iterator mi, mie;
- for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) {
- emitCode("SDOperand LSI_" + *mi + " = "
- "CurDAG->getMemOperand(cast<LSBaseSDNode>(" +
- *mi + ")->getMemOperand());");
- AllOps.push_back("LSI_" + *mi);
- }
- }
-
// Emit all the chain and CopyToReg stuff.
bool ChainEmitted = NodeHasChain;
if (NodeHasChain)
}
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";