diff options
author | Chris Lattner <sabre@nondot.org> | 2010-03-01 21:49:54 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-03-01 21:49:54 +0000 |
commit | adc5347b54fa71368b7b93f003993ad90da99135 (patch) | |
tree | ff813abe5bbcb2f5a6fc49c5021b8e0b6d1421f6 | |
parent | d44f16fce7b23d61e0b10cfdca3d10869b0236ae (diff) |
optimize tblgen compile time by eliminating the old isel.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97504 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | utils/TableGen/DAGISelEmitter.cpp | 1757 | ||||
-rw-r--r-- | utils/TableGen/DAGISelEmitter.h | 16 |
2 files changed, 3 insertions, 1770 deletions
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index bc57428f78..8816c9c0e7 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -14,42 +14,13 @@ #include "DAGISelEmitter.h" #include "DAGISelMatcher.h" #include "Record.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Debug.h" -#include <algorithm> -#include <deque> -#include <iostream> using namespace llvm; -#define ENABLE_NEW_ISEL - - -static cl::opt<bool> -GenDebug("gen-debug", cl::desc("Generate debug code"), cl::init(false)); - //===----------------------------------------------------------------------===// // DAGISelEmitter Helper methods // -/// getNodeName - The top level Select_* functions have an "SDNode* N" -/// argument. When expanding the pattern-matching code, the intermediate -/// variables have type SDValue. This function provides a uniform way to -/// reference the underlying "SDNode *" for both cases. -static std::string getNodeName(const std::string &S) { - if (S == "N") return S; - return S + ".getNode()"; -} - -/// getNodeValue - Similar to getNodeName, except it provides a uniform -/// way to access the SDValue for both cases. -static std::string getValueName(const std::string &S) { - if (S == "N") return "SDValue(N, 0)"; - return S; -} - /// getPatternSize - Return the 'size' of this pattern. We want to match large /// patterns before small ones. This is used to determine the size of a /// pattern. @@ -135,106 +106,6 @@ static unsigned getResultPatternSize(TreePatternNode *P, return Cost; } -// PatternSortingPredicate - return true if we prefer to match LHS before RHS. -// In particular, we want to match maximal patterns first and lowest cost within -// a particular complexity first. -struct PatternSortingPredicate { - PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {} - CodeGenDAGPatterns &CGP; - - typedef std::pair<unsigned, std::string> CodeLine; - typedef std::vector<CodeLine> CodeList; - - bool operator()(const std::pair<const PatternToMatch*, CodeList> &LHSPair, - const std::pair<const PatternToMatch*, CodeList> &RHSPair) { - const PatternToMatch *LHS = LHSPair.first; - const PatternToMatch *RHS = RHSPair.first; - - unsigned LHSSize = getPatternSize(LHS->getSrcPattern(), CGP); - unsigned RHSSize = getPatternSize(RHS->getSrcPattern(), CGP); - LHSSize += LHS->getAddedComplexity(); - RHSSize += RHS->getAddedComplexity(); - if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost - if (LHSSize < RHSSize) return false; - - // If the patterns have equal complexity, compare generated instruction cost - unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP); - unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP); - if (LHSCost < RHSCost) return true; - if (LHSCost > RHSCost) return false; - - return getResultPatternSize(LHS->getDstPattern(), CGP) < - getResultPatternSize(RHS->getDstPattern(), CGP); - } -}; - -/// getRegisterValueType - Look up and return the ValueType of the specified -/// register. If the register is a member of multiple register classes which -/// have different associated types, return MVT::Other. -static MVT::SimpleValueType getRegisterValueType(Record *R, - const CodeGenTarget &T) { - bool FoundRC = false; - MVT::SimpleValueType VT = MVT::Other; - const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses(); - std::vector<CodeGenRegisterClass>::const_iterator RC; - std::vector<Record*>::const_iterator Element; - - for (RC = RCs.begin() ; RC != RCs.end() ; RC++) { - Element = find((*RC).Elements.begin(), (*RC).Elements.end(), R); - if (Element != (*RC).Elements.end()) { - if (!FoundRC) { - FoundRC = true; - VT = (*RC).getValueTypeNum(0); - } else { - // In multiple RC's - if (VT != (*RC).getValueTypeNum(0)) { - // Types of the RC's do not agree. Return MVT::Other. The - // target is responsible for handling this. - return MVT::Other; - } - } - } - } - return VT; -} - -static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) { - return CGP.getSDNodeInfo(Op).getEnumName(); -} - -//===----------------------------------------------------------------------===// -// Node Transformation emitter implementation. -// -void DAGISelEmitter::EmitNodeTransforms(raw_ostream &OS) { - // Walk the pattern fragments, adding them to a map, which sorts them by - // name. - typedef std::map<std::string, CodeGenDAGPatterns::NodeXForm> NXsByNameTy; - NXsByNameTy NXsByName; - - for (CodeGenDAGPatterns::nx_iterator I = CGP.nx_begin(), E = CGP.nx_end(); - I != E; ++I) - NXsByName.insert(std::make_pair(I->first->getName(), I->second)); - - OS << "\n// Node transformations.\n"; - - for (NXsByNameTy::iterator I = NXsByName.begin(), E = NXsByName.end(); - I != E; ++I) { - Record *SDNode = I->second.first; - std::string Code = I->second.second; - - if (Code.empty()) continue; // Empty code? Skip it. - - std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName(); - const char *C2 = ClassName == "SDNode" ? "N" : "inN"; - - OS << "inline SDValue Transform_" << I->first << "(SDNode *" << C2 - << ") {\n"; - if (ClassName != "SDNode") - OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n"; - OS << Code << "\n}\n"; - } -} - //===----------------------------------------------------------------------===// // Predicate emitter implementation. // @@ -280,1623 +151,12 @@ void DAGISelEmitter::EmitPredicateFunctions(raw_ostream &OS) { OS << "\n\n"; } - -//===----------------------------------------------------------------------===// -// PatternCodeEmitter implementation. -// -class PatternCodeEmitter { -private: - CodeGenDAGPatterns &CGP; - - // Predicates. - std::string PredicateCheck; - // Pattern cost. - unsigned Cost; - // Instruction selector pattern. - TreePatternNode *Pattern; - // Matched instruction. - TreePatternNode *Instruction; - - // Node to name mapping - std::map<std::string, std::string> VariableMap; - // 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 - /// [when 0], or initialization code to emit [when 2]. - std::vector<std::pair<unsigned, std::string> > &GeneratedCode; - /// GeneratedDecl - This is the set of all SDValue declarations needed for - /// the set of patterns for each top-level opcode. - std::set<std::string> &GeneratedDecl; - /// TargetOpcodes - The target specific opcodes used by the resulting - /// instructions. - std::vector<std::string> &TargetOpcodes; - std::vector<std::string> &TargetVTs; - /// OutputIsVariadic - Records whether the instruction output pattern uses - /// variable_ops. This requires that the Emit function be passed an - /// additional argument to indicate where the input varargs operands - /// begin. - bool &OutputIsVariadic; - /// NumInputRootOps - Records the number of operands the root node of the - /// input pattern has. This information is used in the generated code to - /// pass to Emit functions when variable_ops processing is needed. - unsigned &NumInputRootOps; - - std::string ChainName; - unsigned TmpNo; - unsigned OpcNo; - unsigned VTNo; - - void emitCheck(const std::string &S) { - if (!S.empty()) - GeneratedCode.push_back(std::make_pair(1, S)); - } - void emitCode(const std::string &S) { - if (!S.empty()) - GeneratedCode.push_back(std::make_pair(0, S)); - } - void emitInit(const std::string &S) { - if (!S.empty()) - GeneratedCode.push_back(std::make_pair(2, S)); - } - void emitDecl(const std::string &S) { - assert(!S.empty() && "Invalid declaration"); - GeneratedDecl.insert(S); - } - void emitOpcode(const std::string &Opc) { - TargetOpcodes.push_back(Opc); - OpcNo++; - } - void emitVT(const std::string &VT) { - TargetVTs.push_back(VT); - VTNo++; - } -public: - PatternCodeEmitter(CodeGenDAGPatterns &cgp, std::string predcheck, - TreePatternNode *pattern, TreePatternNode *instr, - std::vector<std::pair<unsigned, std::string> > &gc, - std::set<std::string> &gd, - std::vector<std::string> &to, - std::vector<std::string> &tv, - bool &oiv, - unsigned &niro) - : CGP(cgp), PredicateCheck(predcheck), Pattern(pattern), Instruction(instr), - GeneratedCode(gc), GeneratedDecl(gd), - TargetOpcodes(to), TargetVTs(tv), - OutputIsVariadic(oiv), NumInputRootOps(niro), - TmpNo(0), OpcNo(0), VTNo(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, TreePatternNode *P, - const std::string &RootName, const std::string &ChainSuffix, - bool &FoundChain); - - void EmitChildMatchCode(TreePatternNode *Child, TreePatternNode *Parent, - const std::string &RootName, - const std::string &ChainSuffix, bool &FoundChain); - - /// EmitResultCode - Emit the action for a pattern. Now that it has matched - /// we actually have to build a DAG! - std::vector<std::string> - EmitResultCode(TreePatternNode *N, std::vector<Record*> DstRegs, - bool InFlagDecled, bool ResNodeDecled, - bool LikeLeaf = false, bool isRoot = false); - - /// InsertOneTypeCheck - Insert a type-check for an unresolved type in 'Pat' - /// and add it to the tree. 'Pat' and 'Other' are isomorphic trees except that - /// 'Pat' may be missing types. If we find an unresolved type to add a check - /// for, this returns true otherwise false if Pat has all types. - bool InsertOneTypeCheck(TreePatternNode *Pat, TreePatternNode *Other, - const std::string &Prefix, bool isRoot = false) { - // Did we find one? - if (Pat->getExtTypes() != Other->getExtTypes()) { - // Move a type over from 'other' to 'pat'. - Pat->setTypes(Other->getExtTypes()); - // The top level node type is checked outside of the select function. - if (!isRoot) - emitCheck(Prefix + ".getValueType() == " + - getName(Pat->getTypeNum(0))); - return true; - } - - unsigned OpNo = (unsigned)Pat->NodeHasProperty(SDNPHasChain, CGP); - for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i, ++OpNo) - if (InsertOneTypeCheck(Pat->getChild(i), Other->getChild(i), - Prefix + utostr(OpNo))) - return true; - return false; - } - -private: - /// EmitInFlagSelectCode - Emit the flag operands for the DAG that is - /// being built. - void EmitInFlagSelectCode(TreePatternNode *N, const std::string &RootName, - bool &ChainEmitted, bool &InFlagDecled, - bool &ResNodeDecled, bool isRoot = false) { - const CodeGenTarget &T = CGP.getTargetInfo(); - unsigned OpNo = (unsigned)N->NodeHasProperty(SDNPHasChain, CGP); - for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) { - TreePatternNode *Child = N->getChild(i); - if (!Child->isLeaf()) { - EmitInFlagSelectCode(Child, RootName + utostr(OpNo), ChainEmitted, - InFlagDecled, ResNodeDecled); - } else { - if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) { - if (!Child->getName().empty()) { - std::string Name = RootName + utostr(OpNo); - if (Duplicates.find(Name) != Duplicates.end()) - // A duplicate! Do not emit a copy for this node. - continue; - } - - Record *RR = DI->getDef(); - if (RR->isSubClassOf("Register")) { - MVT::SimpleValueType RVT = getRegisterValueType(RR, T); - if (RVT == MVT::Flag) { - if (!InFlagDecled) { - emitCode("SDValue InFlag = " + - getValueName(RootName + utostr(OpNo)) + ";"); - InFlagDecled = true; - } else - emitCode("InFlag = " + - getValueName(RootName + utostr(OpNo)) + ";"); - } else { - if (!ChainEmitted) { - emitCode("SDValue Chain = CurDAG->getEntryNode();"); - ChainName = "Chain"; - ChainEmitted = true; - } - if (!InFlagDecled) { - emitCode("SDValue InFlag(0, 0);"); - InFlagDecled = true; - } - std::string Decl = (!ResNodeDecled) ? "SDNode *" : ""; - emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName + - ", " + getNodeName(RootName) + "->getDebugLoc()" + - ", " + getQualifiedName(RR) + - ", " + getValueName(RootName + utostr(OpNo)) + - ", InFlag).getNode();"); - ResNodeDecled = true; - emitCode(ChainName + " = SDValue(ResNode, 0);"); - emitCode("InFlag = SDValue(ResNode, 1);"); - } - } - } - } - } - - if (N->NodeHasProperty(SDNPInFlag, CGP)) { - if (!InFlagDecled) { - emitCode("SDValue InFlag = " + getNodeName(RootName) + - "->getOperand(" + utostr(OpNo) + ");"); - InFlagDecled = true; - } else - abort(); - emitCode("InFlag = " + getNodeName(RootName) + - "->getOperand(" + utostr(OpNo) + ");"); - } - } -}; - - -/// 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 PatternCodeEmitter::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()) { - if (N->NodeHasProperty(SDNPMemOperand, CGP)) - LSI.push_back(getNodeName(RootName)); - } - - bool isRoot = (P == NULL); - // Emit instruction predicates. Each predicate is just a string for now. - if (isRoot) { - // Record input varargs info. - NumInputRootOps = N->getNumChildren(); - emitCheck(PredicateCheck); - } - - if (N->isLeaf()) { - if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { - emitCheck("cast<ConstantSDNode>(" + getNodeName(RootName) + - ")->getSExtValue() == INT64_C(" + - itostr(II->getValue()) + ")"); - return; - } - assert(N->getComplexPatternInfo(CGP) != 0 && - "Cannot match this as a leaf value!"); - } - - // If this node has a name associated with it, capture it in VariableMap. If - // we already saw this in the pattern, emit code to verify dagness. - if (!N->getName().empty()) { - std::string &VarMapEntry = VariableMap[N->getName()]; - if (VarMapEntry.empty()) { - VarMapEntry = RootName; - } else { - // If we get here, this is a second reference to a specific name. 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 same as the - // previously named thing. - emitCheck(VarMapEntry + " == " + RootName); - return; - } - } - - - // Emit code to load the child nodes and match their contents recursively. - unsigned OpNo = 0; - bool NodeHasChain = N->NodeHasProperty(SDNPHasChain, CGP); - bool HasChain = N->TreeHasProperty(SDNPHasChain, CGP); - if (HasChain) { - if (NodeHasChain) - OpNo = 1; - if (!isRoot) { - // Check if it's profitable to fold the node. e.g. Check for multiple uses - // of actual result? - std::string ParentName(RootName.begin(), RootName.end()-1); - if (!NodeHasChain) { - // If this is just an interior node, check to see if it has a single - // use. If the node has multiple uses and the pattern has a load as - // an operand, then we can't fold the load. - emitCheck(getValueName(RootName) + ".hasOneUse()"); - } else if (!N->isLeaf()) { // ComplexPatterns do their own legality check. - // 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]-------| - - // We know we need the check if N's parent is not the root. - bool NeedCheck = P != Pattern; - if (!NeedCheck) { - // If the parent is the root and the node has more than one operand, - // we need to check. - const SDNodeInfo &PInfo = CGP.getSDNodeInfo(P->getOperator()); - NeedCheck = - P->getOperator() == CGP.get_intrinsic_void_sdnode() || - P->getOperator() == CGP.get_intrinsic_w_chain_sdnode() || - P->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() || - PInfo.getNumOperands() > 1 || - PInfo.hasProperty(SDNPHasChain) || - PInfo.hasProperty(SDNPInFlag) || - PInfo.hasProperty(SDNPOptInFlag); - } - - if (NeedCheck) { - emitCheck("IsProfitableToFold(" + getValueName(RootName) + - ", " + getNodeName(ParentName) + ", N)"); - emitCheck("IsLegalToFold(" + getValueName(RootName) + - ", " + getNodeName(ParentName) + ", N)"); - } else { - // Otherwise, just verify that the node only has a single use. - emitCheck(getValueName(RootName) + ".hasOneUse()"); - } - } - } - - if (NodeHasChain) { - if (FoundChain) { - emitCheck("IsChainCompatible(" + ChainName + ".getNode(), " + - getNodeName(RootName) + ")"); - OrigChains.push_back(std::make_pair(ChainName, - getValueName(RootName))); - } else - FoundChain = true; - ChainName = "Chain" + ChainSuffix; - - if (!N->getComplexPatternInfo(CGP) || - isRoot) - emitInit("SDValue " + ChainName + " = " + getNodeName(RootName) + - "->getOperand(0);"); - } - } - - // If there are node predicates for this, emit the calls. - for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i) - emitCheck(N->getPredicateFns()[i] + "(" + getNodeName(RootName) + ")"); - - // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is - // a constant without a predicate fn that has more that one bit set, handle - // this as a special case. This is usually for targets that have special - // handling of certain large constants (e.g. alpha with it's 8/16/32-bit - // handling stuff). Using these instructions is often far more efficient - // than materializing the constant. Unfortunately, both the instcombiner - // and the dag combiner can often infer that bits are dead, and thus drop - // them from the mask in the dag. For example, it might turn 'AND X, 255' - // into 'AND X, 254' if it knows the low bit is set. Emit code that checks - // to handle this. - if (!N->isLeaf() && - (N->getOperator()->getName() == "and" || - N->getOperator()->getName() == "or") && - N->getChild(1)->isLeaf() && - N->getChild(1)->getPredicateFns().empty()) { - if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) { - if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits. - emitInit("SDValue " + RootName + "0" + " = " + - getNodeName(RootName) + "->getOperand(" + utostr(0) + ");"); - emitInit("SDValue " + RootName + "1" + " = " + - getNodeName(RootName) + "->getOperand(" + utostr(1) + ");"); - - unsigned NTmp = TmpNo++; - emitCode("ConstantSDNode *Tmp" + utostr(NTmp) + - " = dyn_cast<ConstantSDNode>(" + - getNodeName(RootName + "1") + ");"); - emitCheck("Tmp" + utostr(NTmp)); - const char *MaskPredicate = N->getOperator()->getName() == "or" - ? "CheckOrMask(" : "CheckAndMask("; - emitCheck(MaskPredicate + getValueName(RootName + "0") + - ", Tmp" + utostr(NTmp) + - ", INT64_C(" + itostr(II->getValue()) + "))"); - - EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0), - ChainSuffix + utostr(0), FoundChain); - return; - } - } - } - - for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) { - emitInit("SDValue " + getValueName(RootName + utostr(OpNo)) + " = " + - getNodeName(RootName) + "->getOperand(" + utostr(OpNo) + ");"); - - EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo), - ChainSuffix + utostr(OpNo), FoundChain); - } - - // Handle complex patterns. - if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) { - std::string Fn = CP->getSelectFunc(); - unsigned NumOps = CP->getNumOperands(); - for (unsigned i = 0; i < NumOps; ++i) { - emitDecl("CPTmp" + RootName + "_" + utostr(i)); - emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";"); - } - if (CP->hasProperty(SDNPHasChain)) { - emitDecl("CPInChain"); - emitDecl("Chain" + ChainSuffix); - emitCode("SDValue CPInChain;"); - emitCode("SDValue Chain" + ChainSuffix + ";"); - } - - std::string Code = Fn + "(N, "; // always pass in the root. - Code += getValueName(RootName); - for (unsigned i = 0; i < NumOps; i++) - Code += ", CPTmp" + RootName + "_" + utostr(i); - if (CP->hasProperty(SDNPHasChain)) { - ChainName = "Chain" + ChainSuffix; - Code += ", CPInChain, " + ChainName; - } - emitCheck(Code + ")"); - } -} - -void PatternCodeEmitter::EmitChildMatchCode(TreePatternNode *Child, - TreePatternNode *Parent, - const std::string &RootName, - const std::string &ChainSuffix, - bool &FoundChain) { - if (!Child->isLeaf()) { - // If it's not a leaf, recursively match. - const SDNodeInfo &CInfo = CGP.getSDNodeInfo(Child->getOperator()); - emitCheck(getNodeName(RootName) + "->getOpcode() == " + - CInfo.getEnumName()); - EmitMatchCode(Child, Parent, RootName, ChainSuffix, FoundChain); - bool HasChain = false; - if (Child->NodeHasProperty(SDNPHasChain, CGP)) { - HasChain = true; - FoldedChains.push_back(std::make_pair(getValueName(RootName), - CInfo.getNumResults())); - } - if (Child->NodeHasProperty(SDNPOutFlag, CGP)) { - assert(FoldedFlag.first == "" && FoldedFlag.second == 0 && - "Pattern folded multiple nodes which produce flags?"); - FoldedFlag = std::make_pair(getValueName(RootName), - CInfo.getNumResults() + (unsigned)HasChain); - } - return; - } - - if (const ComplexPattern *CP = Child->getComplexPatternInfo(CGP)) { - EmitMatchCode(Child, Parent, RootName, ChainSuffix, FoundChain); - bool HasChain = false; - - if (Child->NodeHasProperty(SDNPHasChain, CGP)) { - HasChain = true; - const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Parent->getOperator()); - FoldedChains.push_back(std::make_pair("CPInChain", - PInfo.getNumResults())); - } - if (Child->NodeHasProperty(SDNPOutFlag, CGP)) { - assert(FoldedFlag.first == "" && FoldedFlag.second == 0 && - "Pattern folded multiple nodes which produce flags?"); - FoldedFlag = std::make_pair(getValueName(RootName), - CP->getNumOperands() + (unsigned)HasChain); - } - return; - } - - // 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. - if (!Child->getName().empty()) { - std::string &VarMapEntry = VariableMap[Child->getName()]; - if (VarMapEntry.empty()) { - VarMapEntry = getValueName(RootName); - } else { - // If we get here, this is a second reference to a specific name. - // 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 - // same as the previously named thing. - emitCheck(VarMapEntry + " == " + getValueName(RootName)); - Duplicates.insert(getValueName(RootName)); - return; - } - } - - // Handle leaves of various types. - if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) { - Record *LeafRec = DI->getDef(); - if (LeafRec->isSubClassOf("RegisterClass") || - LeafRec->isSubClassOf("PointerLikeRegClass")) { - // Handle register references. Nothing to do here. - } else if (LeafRec->isSubClassOf("Register")) { - // Handle register references. - } else if (LeafRec->getName() == "srcvalue") { - // Place holder for SRCVALUE nodes. Nothing to do here. - } else if (LeafRec->isSubClassOf("ValueType")) { - // Make sure this is the specified value type. - emitCheck("cast<VTSDNode>(" + getNodeName(RootName) + - ")->getVT() == MVT::" + LeafRec->getName()); - } else if (LeafRec->isSubClassOf("CondCode")) { - // Make sure this is the specified cond code. - emitCheck("cast<CondCodeSDNode>(" + getNodeName(RootName) + - ")->get() == ISD::" + LeafRec->getName()); - } else { -#ifndef NDEBUG - Child->dump(); - errs() << " "; -#endif - assert(0 && "Unknown leaf type!"); - } - - // If there are node predicates for this, emit the calls. - for (unsigned i = 0, e = Child->getPredicateFns().size(); i != e; ++i) - emitCheck(Child->getPredicateFns()[i] + "(" + getNodeName(RootName) + - ")"); - return; - } - - if (IntInit *II = dynamic_cast<IntInit*>(Child->getLeafValue())) { - unsigned NTmp = TmpNo++; - emitCode("ConstantSDNode *Tmp"+ utostr(NTmp) + - " = dyn_cast<ConstantSDNode>("+ - getNodeName(RootName) + ");"); - emitCheck("Tmp" + utostr(NTmp)); - unsigned CTmp = TmpNo++; - emitCode("int64_t CN"+ utostr(CTmp) + - " = Tmp" + utostr(NTmp) + "->getSExtValue();"); - emitCheck("CN" + utostr(CTmp) + " == " - "INT64_C(" +itostr(II->getValue()) + ")"); - return; - } -#ifndef NDEBUG - Child->dump(); -#endif - assert(0 && "Unknown leaf type!"); -} - -/// EmitResultCode - Emit the action for a pattern. Now that it has matched -/// we actually have to build a DAG! -std::vector<std::string> -PatternCodeEmitter::EmitResultCode(TreePatternNode *N, - std::vector<Record*> DstRegs, - bool InFlagDecled, bool ResNodeDecled, - bool LikeLeaf, bool isRoot) { - // List of arguments of getMachineNode() or SelectNodeTo(). - std::vector<std::string> NodeOps; - // This is something selected from the pattern we matched. - if (!N->getName().empty()) { - const std::string &VarName = N->getName(); - std::string Val = VariableMap[VarName]; - if (Val.empty()) { - errs() << "Variable '" << VarName << " referenced but not defined " - << "and not caught earlier!\n"; - abort(); - } - - unsigned ResNo = TmpNo++; - 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: - errs() << "Cannot handle " << getEnumName(N->getTypeNum(0)) - << " type as an immediate constant. Aborting\n"; - abort(); - case MVT::i1: CastType = "bool"; break; - case MVT::i8: CastType = "unsigned char"; break; - case MVT::i16: CastType = "unsigned short"; break; - case MVT::i32: CastType = "unsigned"; break; - case MVT::i64: CastType = "uint64_t"; break; - } - emitCode("SDValue " + TmpVar + - " = CurDAG->getTargetConstant(((" + CastType + - ") cast<ConstantSDNode>(" + Val + ")->getZExtValue()), " + - getEnumName(N->getTypeNum(0)) + ");"); - NodeOps.push_back(getValueName(TmpVar)); - } else if (!N->isLeaf() && N->getOperator()->getName() == "fpimm") { - assert(N->getExtTypes().size() == 1 && "Multiple types not handled!"); - std::string TmpVar = "Tmp" + utostr(ResNo); - emitCode("SDValue " + TmpVar + - " = CurDAG->getTargetConstantFP(*cast<ConstantFPSDNode>(" + - Val + ")->getConstantFPValue(), cast<ConstantFPSDNode>(" + - Val + ")->getValueType(0));"); - NodeOps.push_back(getValueName(TmpVar)); - } else if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) { - for (unsigned i = 0; i < CP->getNumOperands(); ++i) - NodeOps.push_back(getValueName("CPTmp" + Val + "_" + utostr(i))); - } else { - // This node, probably wrapped in a SDNodeXForm, behaves like a leaf - // node even if it isn't one. Don't select it. - if (!LikeLeaf) { - if (isRoot && N->isLeaf()) { - emitCode("ReplaceUses(SDValue(N, 0), " + Val + ");"); - emitCode("return NULL;"); - } - } - NodeOps.push_back(getValueName(Val)); - } - return NodeOps; - } - if (N->isLeaf()) { - // If this is an explicit register reference, handle it. - if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) { - unsigned ResNo = TmpNo++; - if (DI->getDef()->isSubClassOf("Register")) { - emitCode("SDValue Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" + - getQualifiedName(DI->getDef()) + ", " + - getEnumName(N->getTypeNum(0)) + ");"); - NodeOps.push_back(getValueName("Tmp" + utostr(ResNo))); - return NodeOps; - } else if (DI->getDef()->getName() == "zero_reg") { - emitCode("SDValue Tmp" + utostr(ResNo) + - " = CurDAG->getRegister(0, " + - getEnumName(N->getTypeNum(0)) + ");"); - NodeOps.push_back(getValueName("Tmp" + utostr(ResNo))); - return NodeOps; - } else if (DI->getDef()->isSubClassOf("RegisterClass")) { - // Handle a reference to a register class. This is used - // in COPY_TO_SUBREG instructions. - emitCode("SDValue Tmp" + utostr(ResNo) + - " = CurDAG->getTargetConstant(" + - getQualifiedName(DI->getDef()) + "RegClassID, " + - "MVT::i32);"); - NodeOps.push_back(getValueName("Tmp" + utostr(ResNo))); - return NodeOps; - } - } else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { - unsigned ResNo = TmpNo++; - assert(N->getExtTypes().size() == 1 && "Multiple types not handled!"); - emitCode("SDValue Tmp" + utostr(ResNo) + - " = CurDAG->getTargetConstant(0x" + - utohexstr((uint64_t) II->getValue()) + - "ULL, " + getEnumName(N->getTypeNum(0)) + ");"); - NodeOps.push_back(getValueName("Tmp" + utostr(ResNo))); - return NodeOps; - } - -#ifndef NDEBUG - N->dump(); -#endif - assert(0 && "Unknown leaf type!"); - return NodeOps; - } - - Record *Op = N->getOperator(); - if (Op->isSubClassOf("Instruction")) { - const CodeGenTarget &CGT = CGP.getTargetInfo(); - CodeGenInstruction &II = CGT.getInstruction(Op->getName()); - const DAGInstruction &Inst = CGP.getInstruction(Op); - const TreePattern *InstPat = Inst.getPattern(); - // FIXME: Assume actual pattern comes before "implicit". - TreePatternNode *InstPatNode = - isRoot ? (InstPat ? InstPat->getTree(0) : Pattern) - : (InstPat ? InstPat->getTree(0) : NULL); - if (InstPatNode && !InstPatNode->isLeaf() && - InstPatNode->getOperator()->getName() == "set") { - InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1); - } - bool IsVariadic = isRoot && II.isVariadic; - // FIXME: fix how we deal with physical register operands. - bool HasImpInputs = isRoot && Inst.getNumImpOperands() > 0; - bool HasImpResults = isRoot && DstRegs.size() > 0; - bool NodeHasOptInFlag = isRoot && - Pattern->TreeHasProperty(SDNPOptInFlag, CGP); - bool NodeHasInFlag = isRoot && - Pattern->TreeHasProperty(SDNPInFlag, CGP); - bool NodeHasOutFlag = isRoot && - Pattern->TreeHasProperty(SDNPOutFlag, CGP); - bool NodeHasChain = InstPatNode && - InstPatNode->TreeHasProperty(SDNPHasChain, CGP); - bool InputHasChain = isRoot && Pattern->NodeHasProperty(SDNPHasChain, CGP); - unsigned NumResults = Inst.getNumResults(); - unsigned NumDstRegs = HasImpResults ? DstRegs.size() : 0; - - // Record output varargs info. - OutputIsVariadic = IsVariadic; - - if (NodeHasOptInFlag) { - emitCode("bool HasInFlag = " - "(N->getOperand(N->getNumOperands()-1).getValueType() == " - "MVT::Flag);"); - } - if (IsVariadic) - emitCode("SmallVector<SDValue, 8> Ops" + utostr(OpcNo) + ";"); - - // How many results is this pattern expected to produce? - unsigned NumPatResults = 0; - for (unsigned i = 0, e = Pattern->getExtTypes().size(); i != e; i++) { - MVT::SimpleValueType VT = Pattern->getTypeNum(i); - if (VT != MVT::isVoid && VT != MVT::Flag) - NumPatResults++; - } - - if (OrigChains.size() > 0) { - // The original input chain is being ignored. If it is not just - // pointing to the op that's being folded, we should create a - // TokenFactor with it and the chain of the folded op as the new chain. - // We could potentially be doing multiple levels of folding, in that - // case, the TokenFactor can have more operands. - emitCode("SmallVector<SDValue, 8> InChains;"); - for (unsigned i = 0, e = OrigChains.size(); i < e; ++i) { - emitCode("if (" + OrigChains[i].first + ".getNode() != " + - OrigChains[i].second + ".getNode()) {"); - emitCode(" InChains.push_back(" + OrigChains[i].first + ");"); - emitCode("}"); - } - emitCode("InChains.push_back(" + ChainName + ");"); - emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, " - "N->getDebugLoc(), MVT::Other, " - "&InChains[0], InChains.size());"); - if (GenDebug) { - emitCode("CurDAG->setSubgraphColor(" + ChainName + - ".getNode(), \"yellow\");"); - emitCode("CurDAG->setSubgraphColor(" + ChainName + - ".getNode(), \"black\");"); - } - } - - // Loop over all of the operands of the instruction pattern, emitting code - // to fill them all in. The node 'N' usually has number children equal to - // the number of input operands of the ins |