diff --git a/include/llvm/CodeGen/DAGISelHeader.h b/include/llvm/CodeGen/DAGISelHeader.h index 8cd11f6d267..70c2e02ff4f 100644 --- a/include/llvm/CodeGen/DAGISelHeader.h +++ b/include/llvm/CodeGen/DAGISelHeader.h @@ -217,7 +217,8 @@ enum BuiltinOpcodes { OPC_CheckComplexPat, OPC_CheckAndImm1, OPC_CheckAndImm2, OPC_CheckAndImm4, OPC_CheckAndImm8, OPC_CheckOrImm1, OPC_CheckOrImm2, OPC_CheckOrImm4, OPC_CheckOrImm8, - OPC_CheckFoldableChainNode + OPC_CheckFoldableChainNode, + OPC_CheckChainCompatible }; struct MatchScope { @@ -409,6 +410,13 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, continue; } + case OPC_CheckChainCompatible: { + unsigned PrevNode = MatcherTable[MatcherIndex++]; + assert(PrevNode < RecordedNodes.size() && "Invalid CheckChainCompatible"); + if (!IsChainCompatible(RecordedNodes[PrevNode].getNode(), N.getNode())) + break; + continue; + } } // If the code reached this point, then the match failed pop out to the next diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index d7519cec292..83061093bc1 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -111,3 +111,9 @@ void CheckFoldableChainNodeMatcherNode::print(raw_ostream &OS, OS.indent(indent) << "CheckFoldableChainNode\n"; printChild(OS, indent); } + +void CheckChainCompatibleMatcherNode::print(raw_ostream &OS, + unsigned indent) const { + OS.indent(indent) << "CheckChainCompatibleMatcherNode " << PreviousOp << "\n"; + printChild(OS, indent); +} diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index 53cf923e703..3aa29cdbe25 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -50,7 +50,8 @@ public: CheckComplexPat, CheckAndImm, CheckOrImm, - CheckFoldableChainNode + CheckFoldableChainNode, + CheckChainCompatible }; const KindTy Kind; @@ -380,6 +381,25 @@ public: virtual void print(raw_ostream &OS, unsigned indent = 0) const; }; +/// CheckChainCompatibleMatcherNode - Verify that the current node's chain +/// operand is 'compatible' with the specified recorded node's. +class CheckChainCompatibleMatcherNode : public MatcherNodeWithChild { + unsigned PreviousOp; +public: + CheckChainCompatibleMatcherNode(unsigned previousop) + : MatcherNodeWithChild(CheckChainCompatible), PreviousOp(previousop) {} + + unsigned getPreviousOp() const { return PreviousOp; } + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == CheckChainCompatible; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; + + + } // end namespace llvm #endif diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 9b37254cbdd..8e29c471723 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -204,6 +204,10 @@ EmitMatcher(const MatcherNode *N, unsigned Indent) { case MatcherNode::CheckFoldableChainNode: OS << "OPC_CheckFoldableChainNode,\n"; return 1; + case MatcherNode::CheckChainCompatible: + OS << "OPC_CheckChainCompatible, " + << cast(N)->getPreviousOp() << ",\n"; + return 2; } assert(0 && "Unreachable"); return 0; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index e2ffb8e7171..8efcb4f982f 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -165,6 +165,16 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { assert(NextRecordedOperandNo > 1 && "Should have recorded input/result chains at least!"); InputChains.push_back(NextRecordedOperandNo-1); + + // IF we need to check chains, do so, see comment for + // "NodeHasProperty(SDNPHasChain" below. + if (InputChains.size() > 1) { + // FIXME: This is broken, we should eliminate this nonsense completely, + // but we want to produce the same selections that the old matcher does + // for now. + unsigned PrevOp = InputChains[InputChains.size()-2]; + AddMatcherNode(new CheckChainCompatibleMatcherNode(PrevOp)); + } } return; } @@ -229,10 +239,13 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, // sure that folding the chain won't induce cycles in the DAG. This could // happen if there were an intermediate node between the indbr and load, for // example. - - // FIXME: Emit "IsChainCompatible(lastchain.getNode(), CurrentNode)". - // Rename IsChainCompatible -> IsChainUnreachable, add comment about - // complexity. + if (InputChains.size() > 1) { + // FIXME: This is broken, we should eliminate this nonsense completely, + // but we want to produce the same selections that the old matcher does + // for now. + unsigned PrevOp = InputChains[InputChains.size()-2]; + AddMatcherNode(new CheckChainCompatibleMatcherNode(PrevOp)); + } // Don't look at the input chain when matching the tree pattern to the // SDNode.