diff options
-rw-r--r-- | utils/TableGen/DAGISelEmitter.cpp | 204 | ||||
-rw-r--r-- | utils/TableGen/DAGISelEmitter.h | 3 |
2 files changed, 183 insertions, 24 deletions
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index e0d1905..b03d752 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -1856,6 +1856,7 @@ private: std::vector<std::pair<bool, std::string> > &GeneratedCode; std::string ChainName; + bool DoReplace; unsigned TmpNo; void emitCheck(const std::string &S) { @@ -1869,17 +1870,17 @@ private: public: PatternCodeEmitter(DAGISelEmitter &ise, ListInit *preds, TreePatternNode *pattern, TreePatternNode *instr, - std::vector<std::pair<bool, std::string> > &gc) + std::vector<std::pair<bool, std::string> > &gc, bool dorep) : ISE(ise), Predicates(preds), Pattern(pattern), Instruction(instr), - GeneratedCode(gc), TmpNo(0) {} + GeneratedCode(gc), DoReplace(dorep), TmpNo(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 /// matches, and the SDNode for the result has the RootName specified name. - void EmitMatchCode(TreePatternNode *N, const std::string &RootName, - const std::string &ChainSuffix, bool &FoundChain, - bool isRoot = false) { - + void EmitMatchCode(TreePatternNode *N, TreePatternNode *P, + const std::string &RootName, const std::string &ParentName, + const std::string &ChainSuffix, bool &FoundChain) { + bool isRoot = (P == NULL); // Emit instruction predicates. Each predicate is just a string for now. if (isRoot) { std::string PredicateCheck; @@ -1932,8 +1933,9 @@ public: // Emit code to load the child nodes and match their contents recursively. unsigned OpNo = 0; - bool NodeHasChain = NodeHasProperty(N, SDNodeInfo::SDNPHasChain, ISE); - bool HasChain = PatternHasProperty(N, SDNodeInfo::SDNPHasChain, ISE); + bool NodeHasChain = NodeHasProperty (N, SDNodeInfo::SDNPHasChain, ISE); + bool HasChain = PatternHasProperty(N, SDNodeInfo::SDNPHasChain, ISE); + bool HasOutFlag = PatternHasProperty(N, SDNodeInfo::SDNPOutFlag, ISE); bool EmittedUseCheck = false; bool EmittedSlctedCheck = false; if (HasChain) { @@ -1951,10 +1953,49 @@ public: "))"); EmittedSlctedCheck = true; - if (NodeHasChain) - emitCheck("!CodeGenMap.count(" + RootName + ".getValue(" + - utostr(CInfo.getNumResults()) + "))"); + if (NodeHasChain) { + // FIXME: Don't fold if 1) the parent node writes a flag, 2) the node + // has a chain use. + // This a workaround for this problem: + // + // [ch, r : ld] + // ^ ^ + // | | + // [XX]--/ \- [flag : cmp] + // ^ ^ + // | | + // \---[br flag]- + // + // cmp + br should be considered as a single node as they are flagged + // together. So, if the ld is folded into the cmp, the XX node in the + // graph is now both an operand and a use of the ld/cmp/br node. + if (NodeHasProperty(P, SDNodeInfo::SDNPOutFlag, ISE)) + emitCheck(ParentName + ".Val->isOnlyUse(" + RootName + ".Val)"); + + // If the immediate use can somehow reach this node through another + // path, then can't fold it either or it will create a cycle. + // e.g. In the following diagram, XX can reach ld through YY. If + // ld is folded into XX, then YY is both a predecessor and a successor + // of XX. + // + // [ld] + // ^ ^ + // | | + // / \--- + // / [YY] + // | ^ + // [XX]-------| + const SDNodeInfo &PInfo = ISE.getSDNodeInfo(P->getOperator()); + if (PInfo.getNumOperands() > 1 || + PInfo.hasProperty(SDNodeInfo::SDNPHasChain) || + PInfo.hasProperty(SDNodeInfo::SDNPInFlag) || + PInfo.hasProperty(SDNodeInfo::SDNPOptInFlag)) + emitCheck("(" + ParentName + ".getNumOperands() == 1 || !" + + "isNonImmUse(" + ParentName + ".Val, " + RootName + + ".Val))"); + } } + if (NodeHasChain) { if (FoundChain) emitCheck("Chain.Val == " + RootName + ".Val"); @@ -1967,9 +2008,10 @@ public: } // Don't fold any node which reads or writes a flag and has multiple uses. - // FIXME: we really need to separate the concepts of flag and "glue". Those + // FIXME: We really need to separate the concepts of flag and "glue". Those // real flag results, e.g. X86CMP output, can have multiple uses. - // FIXME: If the incoming flag is optional. Then it is ok to fold it. + // FIXME: If the optional incoming flag does not exist. Then it is ok to + // fold it. if (!isRoot && (PatternHasProperty(N, SDNodeInfo::SDNPInFlag, ISE) || PatternHasProperty(N, SDNodeInfo::SDNPOptInFlag, ISE) || @@ -1997,8 +2039,8 @@ public: const SDNodeInfo &CInfo = ISE.getSDNodeInfo(Child->getOperator()); emitCheck(RootName + utostr(OpNo) + ".getOpcode() == " + CInfo.getEnumName()); - EmitMatchCode(Child, RootName + utostr(OpNo), ChainSuffix + utostr(OpNo), - FoundChain); + EmitMatchCode(Child, N, RootName + utostr(OpNo), RootName, + ChainSuffix + utostr(OpNo), FoundChain); if (NodeHasProperty(Child, SDNodeInfo::SDNPHasChain, ISE)) FoldedChains.push_back(std::make_pair(RootName + utostr(OpNo), CInfo.getNumResults())); @@ -2352,9 +2394,15 @@ public: // User does not expect that the instruction produces a chain! bool AddedChain = HasChain && !NodeHasChain; - if (NodeHasChain) - emitCode("CodeGenMap[N.getValue(" + utostr(ValNo++) + ")] = " + + if (NodeHasChain) { + emitCode("CodeGenMap[N.getValue(" + utostr(ValNo) + ")] = " + ChainName + ";"); + if (DoReplace) + emitCode("if (N.ResNo == 0) AddReplacement(N.getValue(" + + utostr(ValNo) + "), " + ChainName + ");"); + ValNo++; + } + if (FoldedChains.size() > 0) { std::string Code; @@ -2362,6 +2410,13 @@ public: Code += "CodeGenMap[" + FoldedChains[j].first + ".getValue(" + utostr(FoldedChains[j].second) + ")] = "; emitCode(Code + ChainName + ";"); + + for (unsigned j = 0, e = FoldedChains.size(); j < e; j++) { + std::string Code = + FoldedChains[j].first + ".getValue(" + + utostr(FoldedChains[j].second) + ")"; + emitCode("AddReplacement(" + Code + ", " + ChainName + ");"); + } } if (NodeHasOutFlag) @@ -2557,15 +2612,15 @@ private: /// stream to match the pattern, and generate the code for the match if it /// succeeds. Returns true if the pattern is not guaranteed to match. void DAGISelEmitter::GenerateCodeForPattern(PatternToMatch &Pattern, - std::vector<std::pair<bool, std::string> > &GeneratedCode) { + std::vector<std::pair<bool, std::string> > &GeneratedCode, + bool DoReplace) { PatternCodeEmitter Emitter(*this, Pattern.getPredicates(), Pattern.getSrcPattern(), Pattern.getDstPattern(), - GeneratedCode); + GeneratedCode, DoReplace); // Emit the matcher, capturing named arguments in VariableMap. bool FoundChain = false; - Emitter.EmitMatchCode(Pattern.getSrcPattern(), "N", "", FoundChain, - true /*the root*/); + Emitter.EmitMatchCode(Pattern.getSrcPattern(), NULL, "N", "", "", FoundChain); // TP - Get *SOME* tree pattern, we don't care which. TreePattern &TP = *PatternFragments.begin()->second; @@ -2785,9 +2840,28 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) { for (std::map<Record*, std::vector<PatternToMatch*>, CompareByRecordName>::iterator PBOI = PatternsByOpcode.begin(), E = PatternsByOpcode.end(); PBOI != E; ++PBOI) { - OS << "SDOperand Select_" << PBOI->first->getName() << "(SDOperand N) {\n"; + const std::string &OpName = PBOI->first->getName(); + OS << "SDOperand Select_" << OpName << "(SDOperand N) {\n"; const SDNodeInfo &OpcodeInfo = getSDNodeInfo(PBOI->first); + bool OptSlctOrder = + (OpcodeInfo.hasProperty(SDNodeInfo::SDNPHasChain) && + OpcodeInfo.getNumResults() > 0); + + if (OptSlctOrder) { + OS << " SDOperand RetVal;\n"; + OS << " if (N.ResNo == " << OpcodeInfo.getNumResults() + << " && N.getValue(0).hasOneUse()) {\n" + << " SDOperand Dummy = " + << "CurDAG->getNode(ISD::HANDLENODE, MVT::Other, N);\n" + << " CodeGenMap[N.getValue(" << OpcodeInfo.getNumResults() + << ")] = Dummy;\n" + << " HolderMap[N.getValue(" << OpcodeInfo.getNumResults() + << ")] = Dummy;\n" + << " return Dummy;\n" + << " }\n"; + } + std::vector<PatternToMatch*> &Patterns = PBOI->second; assert(!Patterns.empty() && "No patterns but map has entry?"); @@ -2802,7 +2876,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) { std::vector<std::pair<PatternToMatch*, CodeList> > CodeForPatterns; for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { CodeList GeneratedCode; - GenerateCodeForPattern(*Patterns[i], GeneratedCode); + GenerateCodeForPattern(*Patterns[i], GeneratedCode, OptSlctOrder); CodeForPatterns.push_back(std::make_pair(Patterns[i], GeneratedCode)); } @@ -2984,6 +3058,90 @@ void DAGISelEmitter::run(std::ostream &OS) { OS << "// Instance var to keep track of multiply used nodes that have \n" << "// already been selected.\n" << "std::map<SDOperand, SDOperand> CodeGenMap;\n"; + + OS << "// Instance var to keep track of mapping of chain generating nodes\n" + << "// and their place holder nodes.\n"; + OS << "std::map<SDOperand, SDOperand> HolderMap;\n"; + OS << "// Instance var to keep track of mapping of place holder nodes\n" + << "// and their replacement nodes.\n"; + OS << "std::map<SDOperand, SDOperand> ReplaceMap;\n"; + + OS << "\n"; + OS << "static void findNonImmUse(SDNode* Use, SDNode* Def, bool &found, " + << "std::set<SDNode *> &Visited) {\n"; + OS << " if (found || !Visited.insert(Use).second) return;\n"; + OS << " for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) {\n"; + OS << " SDNode *N = Use->getOperand(i).Val;\n"; + OS << " if (N->getNodeDepth() >= Def->getNodeDepth()) {\n"; + OS << " if (N != Def) {\n"; + OS << " findNonImmUse(N, Def, found, Visited);\n"; + OS << " } else {\n"; + OS << " found = true;\n"; + OS << " break;\n"; + OS << " }\n"; + OS << " }\n"; + OS << " }\n"; + OS << "}\n"; + + OS << "\n"; + OS << "static bool isNonImmUse(SDNode* Use, SDNode* Def) {\n"; + OS << " std::set<SDNode *> Visited;\n"; + OS << " bool found = false;\n"; + OS << " for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) {\n"; + OS << " SDNode *N = Use->getOperand(i).Val;\n"; + OS << " if (N != Def) {\n"; + OS << " findNonImmUse(N, Def, found, Visited);\n"; + OS << " if (found) break;\n"; + OS << " }\n"; + OS << " }\n"; + OS << " return found;\n"; + OS << "}\n"; + + OS << "\n"; + OS << "// AddReplacement - Note the pending replacement node for a\n" + << "// holder node in ReplaceMap.\n"; + OS << "void AddReplacement(SDOperand N, SDOperand R) {\n"; + OS << " std::map<SDOperand, SDOperand>::iterator HMI = HolderMap.find(N);\n"; + OS << " if (HMI != HolderMap.end()) {\n"; + OS << " ReplaceMap[HMI->second] = R;\n"; + OS << " HolderMap.erase(N);\n"; + OS << " }\n"; + OS << "}\n"; + + OS << "\n"; + OS << "// ReplaceHolders - Replace all the holders with the real target\n"; + OS << "// specific nodes.\n"; + OS << "void ReplaceHolders() {\n"; + OS << " for (std::map<SDOperand, SDOperand>::iterator I = " + << "ReplaceMap.begin(),\n" + << " E = ReplaceMap.end(); I != E; ++I) {\n"; + OS << " SDOperand From = I->first;\n"; + OS << " SDOperand To = I->second;\n"; + OS << " for (SDNode::use_iterator UI = From.Val->use_begin(), " + << "E = From.Val->use_end(); UI != E; ++UI) {\n"; + OS << " SDNode *Use = *UI;\n"; + OS << " std::vector<SDOperand> Ops;\n"; + OS << " for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) {\n"; + OS << " SDOperand O = Use->getOperand(i);\n"; + OS << " if (O.Val == From.Val)\n"; + OS << " Ops.push_back(To);\n"; + OS << " else\n"; + OS << " Ops.push_back(O);\n"; + OS << " }\n"; + OS << " SDOperand U = SDOperand(Use, 0);\n"; + OS << " CurDAG->UpdateNodeOperands(U, Ops);\n"; + OS << " }\n"; + OS << " }\n"; + OS << "}\n"; + + OS << "\n"; + OS << "// SelectRoot - Top level entry to DAG isel.\n"; + OS << "SDOperand SelectRoot(SDOperand N) {\n"; + OS << " SDOperand RetVal = Select(N);\n"; + OS << " ReplaceHolders();\n"; + OS << " ReplaceMap.clear();\n"; + OS << " return RetVal;\n"; + OS << "}\n"; ParseNodeInfo(); ParseNodeTransforms(OS); diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h index 04a87b7..0cc1dbf 100644 --- a/utils/TableGen/DAGISelEmitter.h +++ b/utils/TableGen/DAGISelEmitter.h @@ -471,7 +471,8 @@ private: std::vector<Record*> &InstImpInputs, std::vector<Record*> &InstImpResults); void GenerateCodeForPattern(PatternToMatch &Pattern, - std::vector<std::pair<bool, std::string> > &GeneratedCode); + std::vector<std::pair<bool, std::string> > &GeneratedCode, + bool UseGoto); void EmitPatterns(std::vector<std::pair<PatternToMatch*, std::vector<std::pair<bool, std::string> > > > &Patterns, unsigned Indent, std::ostream &OS); |