diff --git a/llvm/include/llvm/CodeGen/DAGISelHeader.h b/llvm/include/llvm/CodeGen/DAGISelHeader.h index 70c2e02ff4f3..fd0c4f1f8572 100644 --- a/llvm/include/llvm/CodeGen/DAGISelHeader.h +++ b/llvm/include/llvm/CodeGen/DAGISelHeader.h @@ -203,7 +203,7 @@ GetInt8(const unsigned char *MatcherTable, unsigned &Idx) { enum BuiltinOpcodes { OPC_Emit, OPC_Push, - OPC_Record, + OPC_RecordNode, OPC_MoveChild, OPC_MoveParent, OPC_CheckSame, @@ -294,7 +294,7 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, MatchScopes.push_back(NewEntry); continue; } - case OPC_Record: + case OPC_RecordNode: // Remember this node, it may end up being an operand in the pattern. RecordedNodes.push_back(N); continue; diff --git a/llvm/utils/TableGen/DAGISelMatcher.cpp b/llvm/utils/TableGen/DAGISelMatcher.cpp index 8b8c9bf98a10..fdefe460a05a 100644 --- a/llvm/utils/TableGen/DAGISelMatcher.cpp +++ b/llvm/utils/TableGen/DAGISelMatcher.cpp @@ -10,6 +10,7 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" #include "CodeGenTarget.h" +#include "Record.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -117,3 +118,19 @@ void CheckChainCompatibleMatcherNode::print(raw_ostream &OS, OS.indent(indent) << "CheckChainCompatibleMatcherNode " << PreviousOp << "\n"; printNext(OS, indent); } + +void EmitIntegerMatcherNode::print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitIntegerMatcherNode " << Val << " VT=" << VT << '\n'; + printNext(OS, indent); +} + +void EmitRegisterMatcherNode::print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitRegisterMatcherNode "; + if (Reg) + OS << Reg->getName(); + else + OS << "zero_reg"; + OS << " VT=" << VT << '\n'; + printNext(OS, indent); +} + diff --git a/llvm/utils/TableGen/DAGISelMatcher.h b/llvm/utils/TableGen/DAGISelMatcher.h index 41fbcb4c84a7..7b6fbdb8bf5e 100644 --- a/llvm/utils/TableGen/DAGISelMatcher.h +++ b/llvm/utils/TableGen/DAGISelMatcher.h @@ -21,6 +21,7 @@ namespace llvm { class PatternToMatch; class raw_ostream; class ComplexPattern; + class Record; MatcherNode *ConvertPatternToMatcher(const PatternToMatch &Pattern, const CodeGenDAGPatterns &CGP); @@ -36,25 +37,31 @@ class MatcherNode { OwningPtr Next; public: enum KindTy { - EmitNode, - Push, // [Push, Dest0, Dest1, Dest2, Dest3] - Record, // [Record] - MoveChild, // [MoveChild, Child#] - MoveParent, // [MoveParent] + // Stack manipulation. + Push, // Push a checking scope. + RecordNode, // Record the current node. + MoveChild, // Move current node to specified child. + MoveParent, // Move current node to parent. - CheckSame, // [CheckSame, N] Fail if not same as prev match. + // Predicate checking. + CheckSame, // Fail if not same as prev match. CheckPatternPredicate, - CheckPredicate, // [CheckPredicate, P] Fail if predicate fails. - CheckOpcode, // [CheckOpcode, Opcode] Fail if not opcode. - CheckType, // [CheckType, MVT] Fail if not correct type. - CheckInteger, // [CheckInteger, int0,int1,int2,...int7] Fail if wrong val. - CheckCondCode, // [CheckCondCode, CondCode] Fail if not condcode. + CheckPredicate, // Fail if node predicate fails. + CheckOpcode, // Fail if not opcode. + CheckType, // Fail if not correct type. + CheckInteger, // Fail if wrong val. + CheckCondCode, // Fail if not condcode. CheckValueType, CheckComplexPat, CheckAndImm, CheckOrImm, CheckFoldableChainNode, - CheckChainCompatible + CheckChainCompatible, + + // Node creation/emisssion. + EmitInteger, // Create a TargetConstant + EmitRegister, // Create a register. + EmitNode }; const KindTy Kind; @@ -77,23 +84,6 @@ protected: void printNext(raw_ostream &OS, unsigned indent) const; }; -/// EmitNodeMatcherNode - This signals a successful match and generates a node. -class EmitNodeMatcherNode : public MatcherNode { - const PatternToMatch &Pattern; -public: - EmitNodeMatcherNode(const PatternToMatch &pattern) - : MatcherNode(EmitNode), Pattern(pattern) {} - - const PatternToMatch &getPattern() const { return Pattern; } - - static inline bool classof(const MatcherNode *N) { - return N->getKind() == EmitNode; - } - - virtual void print(raw_ostream &OS, unsigned indent = 0) const; -}; - - /// PushMatcherNode - This pushes a failure scope on the stack and evaluates /// 'Next'. If 'Next' fails to match, it pops its scope and attempts to /// match 'Failure'. @@ -123,12 +113,12 @@ class RecordMatcherNode : public MatcherNode { std::string WhatFor; public: RecordMatcherNode(const std::string &whatfor) - : MatcherNode(Record), WhatFor(whatfor) {} + : MatcherNode(RecordNode), WhatFor(whatfor) {} const std::string &getWhatFor() const { return WhatFor; } static inline bool classof(const MatcherNode *N) { - return N->getKind() == Record; + return N->getKind() == RecordNode; } virtual void print(raw_ostream &OS, unsigned indent = 0) const; @@ -388,8 +378,60 @@ public: virtual void print(raw_ostream &OS, unsigned indent = 0) const; }; +/// EmitIntegerMatcherNode - This creates a new TargetConstant. +class EmitIntegerMatcherNode : public MatcherNode { + int64_t Val; + MVT::SimpleValueType VT; +public: + EmitIntegerMatcherNode(int64_t val, MVT::SimpleValueType vt) + : MatcherNode(EmitInteger), Val(val), VT(vt) {} + + int64_t getVal() const { return Val; } + MVT::SimpleValueType getVT() const { return VT; } + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == EmitInteger; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; + +/// EmitRegisterMatcherNode - This creates a new TargetConstant. +class EmitRegisterMatcherNode : public MatcherNode { + /// Reg - The def for the register that we're emitting. If this is null, then + /// this is a reference to zero_reg. + Record *Reg; + MVT::SimpleValueType VT; +public: + EmitRegisterMatcherNode(Record *reg, MVT::SimpleValueType vt) + : MatcherNode(EmitRegister), Reg(reg), VT(vt) {} + + Record *getReg() const { return Reg; } + MVT::SimpleValueType getVT() const { return VT; } + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == EmitRegister; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; + +/// EmitNodeMatcherNode - This signals a successful match and generates a node. +class EmitNodeMatcherNode : public MatcherNode { + const PatternToMatch &Pattern; +public: + EmitNodeMatcherNode(const PatternToMatch &pattern) + : MatcherNode(EmitNode), Pattern(pattern) {} + + const PatternToMatch &getPattern() const { return Pattern; } + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == EmitNode; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; - } // end namespace llvm #endif diff --git a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp index 158fe7ff3ab5..92b2a55e9b77 100644 --- a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -125,8 +125,8 @@ EmitMatcher(const MatcherNode *N, unsigned Indent) { << *cast(N)->getPattern().getDstPattern() << "\n"; OS.PadToColumn(Indent*2) << "OPC_Emit, /*XXX*/\n\n"; return 1; - case MatcherNode::Record: - OS << "OPC_Record,"; + case MatcherNode::RecordNode: + OS << "OPC_RecordNode,"; OS.PadToColumn(CommentIndent) << "// " << cast(N)->getWhatFor() << '\n'; return 1; @@ -212,6 +212,11 @@ EmitMatcher(const MatcherNode *N, unsigned Indent) { OS << "OPC_CheckChainCompatible, " << cast(N)->getPreviousOp() << ",\n"; return 2; + + case MatcherNode::EmitInteger: + case MatcherNode::EmitRegister: + // FIXME: Implement. + return 0; } assert(0 && "Unreachable"); return 0; diff --git a/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/llvm/utils/TableGen/DAGISelMatcherGen.cpp index 5f55576ebb6a..88d55b6ab4d7 100644 --- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -397,6 +397,38 @@ void MatcherGen::EmitMatcherCode() { void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, SmallVectorImpl &ResultOps) { + assert(N->isLeaf() && "Must be a leaf"); + + if (IntInit *II = dynamic_cast(N->getLeafValue())) { + AddMatcherNode(new EmitIntegerMatcherNode(II->getValue(),N->getTypeNum(0))); + //ResultOps.push_back(TmpNode(TmpNo++)); + return; + } + + // If this is an explicit register reference, handle it. + if (DefInit *DI = dynamic_cast(N->getLeafValue())) { + if (DI->getDef()->isSubClassOf("Register")) { + AddMatcherNode(new EmitRegisterMatcherNode(DI->getDef(), + N->getTypeNum(0))); + //ResultOps.push_back(TmpNode(TmpNo++)); + return; + } + + if (DI->getDef()->getName() == "zero_reg") { + AddMatcherNode(new EmitRegisterMatcherNode(0, N->getTypeNum(0))); + //ResultOps.push_back(TmpNode(TmpNo++)); + return; + } + +#if 0 + if (DI->getDef()->isSubClassOf("RegisterClass")) { + // Handle a reference to a register class. This is used + // in COPY_TO_SUBREG instructions. + // FIXME: Implement. + } +#endif + } + errs() << "unhandled leaf node: \n"; N->dump(); }