diff --git a/include/llvm/CodeGen/DAGISelHeader.h b/include/llvm/CodeGen/DAGISelHeader.h index 1514dbaa702..41e3b2fb0a1 100644 --- a/include/llvm/CodeGen/DAGISelHeader.h +++ b/include/llvm/CodeGen/DAGISelHeader.h @@ -186,29 +186,30 @@ GetInt1(const unsigned char *MatcherTable, unsigned &Idx) { ALWAYS_INLINE static int16_t GetInt2(const unsigned char *MatcherTable, unsigned &Idx) { - int16_t Val = GetInt1(MatcherTable, Idx); + int16_t Val = (uint8_t)GetInt1(MatcherTable, Idx); Val |= int16_t(GetInt1(MatcherTable, Idx)) << 8; return Val; } ALWAYS_INLINE static int32_t GetInt4(const unsigned char *MatcherTable, unsigned &Idx) { - int32_t Val = GetInt2(MatcherTable, Idx); + int32_t Val = (uint16_t)GetInt2(MatcherTable, Idx); Val |= int32_t(GetInt2(MatcherTable, Idx)) << 16; return Val; } ALWAYS_INLINE static int64_t GetInt8(const unsigned char *MatcherTable, unsigned &Idx) { - int64_t Val = GetInt4(MatcherTable, Idx); + int64_t Val = (uint32_t)GetInt4(MatcherTable, Idx); Val |= int64_t(GetInt4(MatcherTable, Idx)) << 32; return Val; } enum BuiltinOpcodes { - OPC_Emit, OPC_Push, OPC_RecordNode, + OPC_RecordMemRef, + OPC_CaptureFlagInput, OPC_MoveChild, OPC_MoveParent, OPC_CheckSame, @@ -226,9 +227,37 @@ enum BuiltinOpcodes { OPC_CheckChainCompatible, OPC_EmitInteger1, OPC_EmitInteger2, OPC_EmitInteger4, OPC_EmitInteger8, - OPC_EmitRegister + OPC_EmitRegister, + OPC_EmitConvertToTarget, + OPC_EmitMergeInputChains, + OPC_EmitCopyToReg, + OPC_EmitNodeXForm, + OPC_EmitNode }; +enum { + OPFL_None = 0, // Node has no chain or flag input and isn't variadic. + OPFL_Chain = 1, // Node has a chain input. + OPFL_Flag = 2, // Node has a flag input. + OPFL_MemRefs = 4, // Node gets accumulated MemRefs. + OPFL_Variadic0 = 1<<3, // Node is variadic, root has 0 fixed inputs. + OPFL_Variadic1 = 2<<3, // Node is variadic, root has 1 fixed inputs. + OPFL_Variadic2 = 3<<3, // Node is variadic, root has 2 fixed inputs. + OPFL_Variadic3 = 4<<3, // Node is variadic, root has 3 fixed inputs. + OPFL_Variadic4 = 5<<3, // Node is variadic, root has 4 fixed inputs. + OPFL_Variadic5 = 6<<3, // Node is variadic, root has 5 fixed inputs. + OPFL_Variadic6 = 7<<3, // Node is variadic, root has 6 fixed inputs. + + OPFL_VariadicInfo = OPFL_Variadic6 +}; + +/// getNumFixedFromVariadicInfo - Transform an EmitNode flags word into the +/// number of fixed arity values that should be skipped when copying from the +/// root. +static inline int getNumFixedFromVariadicInfo(unsigned Flags) { + return ((Flags&OPFL_VariadicInfo) >> 3)-1; +} + struct MatchScope { /// FailIndex - If this match fails, this is the index to continue with. unsigned FailIndex; @@ -238,10 +267,20 @@ struct MatchScope { /// NumRecordedNodes - The number of recorded nodes when the scope was formed. unsigned NumRecordedNodes; + + /// NumMatchedMemRefs - The number of matched memref entries. + unsigned NumMatchedMemRefs; + + /// InputChain/InputFlag - The current chain/flag + SDValue InputChain, InputFlag; + + /// HasChainNodesMatched - True if the ChainNodesMatched list is non-empty. + bool HasChainNodesMatched; }; SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, unsigned TableSize) { + // FIXME: Should these even be selected? Handle these cases in the caller? switch (NodeToMatch->getOpcode()) { default: break; @@ -272,33 +311,50 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, } assert(!NodeToMatch->isMachineOpcode() && "Node already selected!"); - + + // Set up the node stack with NodeToMatch as the only node on the stack. + SmallVector NodeStack; + SDValue N = SDValue(NodeToMatch, 0); + NodeStack.push_back(N); + + // MatchScopes - Scopes used when matching, if a match failure happens, this + // indicates where to continue checking. SmallVector MatchScopes; // RecordedNodes - This is the set of nodes that have been recorded by the // state machine. SmallVector RecordedNodes; - // Set up the node stack with NodeToMatch as the only node on the stack. - SmallVector NodeStack; - SDValue N = SDValue(NodeToMatch, 0); - NodeStack.push_back(N); + // MatchedMemRefs - This is the set of MemRef's we've seen in the input + // pattern. + SmallVector MatchedMemRefs; + + // These are the current input chain and flag for use when generating nodes. + // Various Emit operations change these. For example, emitting a copytoreg + // uses and updates these. + SDValue InputChain, InputFlag; + + // ChainNodesMatched - If a pattern matches nodes that have input/output + // chains, the OPC_EmitMergeInputChains operation is emitted which indicates + // which ones they are. The result is captured into this list so that we can + // update the chain results when the pattern is complete. + SmallVector ChainNodesMatched; // Interpreter starts at opcode #0. unsigned MatcherIndex = 0; while (1) { assert(MatcherIndex < TableSize && "Invalid index"); switch ((BuiltinOpcodes)MatcherTable[MatcherIndex++]) { - case OPC_Emit: { - errs() << "EMIT NODE\n"; - return 0; - } case OPC_Push: { unsigned NumToSkip = MatcherTable[MatcherIndex++]; MatchScope NewEntry; NewEntry.FailIndex = MatcherIndex+NumToSkip; NewEntry.NodeStackSize = NodeStack.size(); NewEntry.NumRecordedNodes = RecordedNodes.size(); + NewEntry.NumMatchedMemRefs = MatchedMemRefs.size(); + NewEntry.InputChain = InputChain; + NewEntry.InputFlag = InputFlag; + NewEntry.HasChainNodesMatched = !ChainNodesMatched.empty(); MatchScopes.push_back(NewEntry); continue; } @@ -306,6 +362,16 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, // Remember this node, it may end up being an operand in the pattern. RecordedNodes.push_back(N); continue; + case OPC_RecordMemRef: + MatchedMemRefs.push_back(cast(N)->getMemOperand()); + continue; + + case OPC_CaptureFlagInput: + // If the current node has an input flag, capture it in InputFlag. + if (N->getNumOperands() != 0 && + N->getOperand(N->getNumOperands()-1).getValueType() == MVT::Flag) + InputFlag = N->getOperand(N->getNumOperands()-1); + continue; case OPC_MoveChild: { unsigned Child = MatcherTable[MatcherIndex++]; @@ -421,19 +487,22 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, case OPC_CheckChainCompatible: { unsigned PrevNode = MatcherTable[MatcherIndex++]; assert(PrevNode < RecordedNodes.size() && "Invalid CheckChainCompatible"); - if (!IsChainCompatible(RecordedNodes[PrevNode].getNode(), N.getNode())) + SDValue PrevChainedNode = RecordedNodes[PrevNode]; + SDValue ThisChainedNode = RecordedNodes.back(); + + // We have two nodes with chains, verify that their input chains are good. + assert(PrevChainedNode.getOperand(0).getValueType() == MVT::Other && + ThisChainedNode.getOperand(0).getValueType() == MVT::Other && + "Invalid chained nodes"); + + if (!IsChainCompatible(// Input chain of the previous node. + PrevChainedNode.getOperand(0).getNode(), + // Node with chain. + ThisChainedNode.getNode())) break; continue; } - case OPC_EmitRegister: { - unsigned RegNo = MatcherTable[MatcherIndex++]; - MVT::SimpleValueType VT = - (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; - SDValue Reg = CurDAG->getRegister(RegNo, VT); - RecordedNodes.push_back(N); - continue; - } case OPC_EmitInteger1: { MVT::SimpleValueType VT = (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; @@ -458,6 +527,186 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, EmitInteger(GetInt8(MatcherTable, MatcherIndex), VT, RecordedNodes); continue; } + + case OPC_EmitRegister: { + unsigned RegNo = MatcherTable[MatcherIndex++]; + MVT::SimpleValueType VT = + (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + SDValue Reg = CurDAG->getRegister(RegNo, VT); + RecordedNodes.push_back(N); + continue; + } + + case OPC_EmitConvertToTarget: { + // Convert from IMM/FPIMM to target version. + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + SDValue Imm = RecordedNodes[RecNo]; + + if (Imm->getOpcode() == ISD::Constant) { + int64_t Val = cast(Imm)->getZExtValue(); + Imm = CurDAG->getTargetConstant(Val, Imm.getValueType()); + } else if (Imm->getOpcode() == ISD::ConstantFP) { + const ConstantFP *Val=cast(Imm)->getConstantFPValue(); + Imm = CurDAG->getTargetConstantFP(*Val, Imm.getValueType()); + } + + RecordedNodes.push_back(Imm); + continue; + } + + case OPC_EmitMergeInputChains: { + assert(InputChain.getNode() == 0 && + "EmitMergeInputChains should be the first chain producing node"); + // This node gets a list of nodes we matched in the input that have + // chains. We want to token factor all of the input chains to these nodes + // together. However, if any of the input chains is actually one of the + // nodes matched in this pattern, then we have an intra-match reference. + // Ignore these because the newly token factored chain should not refer to + // the old nodes. + unsigned NumChains = MatcherTable[MatcherIndex++]; + assert(NumChains != 0 && "Can't TF zero chains"); + + // The common case here is that we have exactly one chain, which is really + // cheap to handle, just do it. + if (NumChains == 1) { + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + InputChain = RecordedNodes[RecNo].getOperand(0); + assert(InputChain.getValueType() == MVT::Other && "Not a chain"); + continue; + } + + // Read all of the chained nodes. + assert(ChainNodesMatched.empty() && + "Should only have one EmitMergeInputChains per match"); + for (unsigned i = 0; i != NumChains; ++i) { + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + ChainNodesMatched.push_back(RecordedNodes[RecNo].getNode()); + } + + // Walk all the chained nodes, adding the input chains if they are not in + // ChainedNodes (and this, not in the matched pattern). This is an N^2 + // algorithm, but # chains is usually 2 here, at most 3 for MSP430. + SmallVector InputChains; + for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) { + SDValue InChain = ChainNodesMatched[i]->getOperand(0); + assert(InChain.getValueType() == MVT::Other && "Not a chain"); + bool Invalid = false; + for (unsigned j = 0; j != e; ++j) + Invalid |= ChainNodesMatched[j] == InChain.getNode(); + if (!Invalid) + InputChains.push_back(InChain); + } + + SDValue Res; + if (InputChains.size() == 1) + InputChain = InputChains[0]; + else + InputChain = CurDAG->getNode(ISD::TokenFactor, + NodeToMatch->getDebugLoc(), MVT::Other, + &InputChains[0], InputChains.size()); + continue; + } + + case OPC_EmitCopyToReg: { + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + unsigned DestPhysReg = MatcherTable[MatcherIndex++]; + + if (InputChain.getNode() == 0) + InputChain = CurDAG->getEntryNode(); + + InputChain = CurDAG->getCopyToReg(InputChain, NodeToMatch->getDebugLoc(), + DestPhysReg, RecordedNodes[RecNo], + InputFlag); + + InputFlag = InputChain.getValue(1); + continue; + } + + case OPC_EmitNodeXForm: { + unsigned XFormNo = MatcherTable[MatcherIndex++]; + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + RecordedNodes.push_back(RunSDNodeXForm(RecordedNodes[RecNo], XFormNo)); + continue; + } + + case OPC_EmitNode: { + uint16_t TargetOpc = GetInt2(MatcherTable, MatcherIndex); + unsigned EmitNodeInfo = MatcherTable[MatcherIndex++]; + // Get the result VT list. + unsigned NumVTs = MatcherTable[MatcherIndex++]; + assert(NumVTs != 0 && "Invalid node result"); + SmallVector VTs; + for (unsigned i = 0; i != NumVTs; ++i) + VTs.push_back((MVT::SimpleValueType)MatcherTable[MatcherIndex++]); + SDVTList VTList = CurDAG->getVTList(VTs.data(), VTs.size()); + + // Get the operand list. + unsigned NumOps = MatcherTable[MatcherIndex++]; + SmallVector Ops; + for (unsigned i = 0; i != NumOps; ++i) { + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + Ops.push_back(RecordedNodes[RecNo]); + } + + // If there are variadic operands to add, handle them now. + if (EmitNodeInfo & OPFL_VariadicInfo) { + // Determine the start index to copy from. + unsigned FirstOpToCopy = getNumFixedFromVariadicInfo(EmitNodeInfo); + FirstOpToCopy += (EmitNodeInfo & OPFL_Chain) ? 1 : 0; + assert(NodeToMatch->getNumOperands() >= FirstOpToCopy && + "Invalid variadic node"); + // Copy all of the variadic operands, not including a potential flag + // input. + for (unsigned i = FirstOpToCopy, e = NodeToMatch->getNumOperands(); + i != e; ++i) { + SDValue V = NodeToMatch->getOperand(i); + if (V.getValueType() == MVT::Flag) break; + Ops.push_back(V); + } + } + + // If this has chain/flag inputs, add them. + if (EmitNodeInfo & OPFL_Chain) + Ops.push_back(InputChain); + if (EmitNodeInfo & OPFL_Flag) + Ops.push_back(InputFlag); + + // Create the node. + MachineSDNode *Res = CurDAG->getMachineNode(TargetOpc, + NodeToMatch->getDebugLoc(), + VTList, + Ops.data(), Ops.size()); + RecordedNodes.push_back(SDValue(Res, 0)); + + // If the node had chain/flag results, update our notion of the current + // chain and flag. + if (VTs.back() == MVT::Flag) { + InputFlag = SDValue(Res, VTs.size()-1); + if (EmitNodeInfo & OPFL_Chain) + InputChain = SDValue(Res, VTs.size()-2); + } else if (EmitNodeInfo & OPFL_Chain) + InputChain = SDValue(Res, VTs.size()-1); + + // If the OPFL_MemRefs flag is set on this node, slap all of the + // accumulated memrefs onto it. + // + // FIXME: This is vastly incorrect for patterns with multiple outputs + // instructions that access memory and for ComplexPatterns that match + // loads. + if (EmitNodeInfo & OPFL_MemRefs) { + MachineSDNode::mmo_iterator MemRefs = + MF->allocateMemRefsArray(MatchedMemRefs.size()); + std::copy(MatchedMemRefs.begin(), MatchedMemRefs.end(), MemRefs); + Res->setMemRefs(MemRefs, MemRefs + MatchedMemRefs.size()); + } + continue; + } } // If the code reached this point, then the match failed pop out to the next @@ -467,9 +716,19 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, return 0; } - RecordedNodes.resize(MatchScopes.back().NumRecordedNodes); - NodeStack.resize(MatchScopes.back().NodeStackSize); - MatcherIndex = MatchScopes.back().FailIndex; + const MatchScope &LastScope = MatchScopes.back(); + RecordedNodes.resize(LastScope.NumRecordedNodes); + NodeStack.resize(LastScope.NodeStackSize); + + if (LastScope.NumMatchedMemRefs != MatchedMemRefs.size()) + MatchedMemRefs.resize(LastScope.NumMatchedMemRefs); + MatcherIndex = LastScope.FailIndex; + + InputChain = LastScope.InputChain; + InputFlag = LastScope.InputFlag; + if (!LastScope.HasChainNodesMatched) + ChainNodesMatched.clear(); + MatchScopes.pop_back(); } } diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index f404de00de8..55a9d36588c 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -169,7 +169,8 @@ struct PatternSortingPredicate { /// 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) { +static MVT::SimpleValueType getRegisterValueType(Record *R, + const CodeGenTarget &T) { bool FoundRC = false; MVT::SimpleValueType VT = MVT::Other; const std::vector &RCs = T.getRegisterClasses(); @@ -296,8 +297,6 @@ private: // Node to name mapping std::map VariableMap; - // Node to operator mapping - std::map OperatorMap; // Name of the folded node which produces a flag. std::pair FoldedFlag; // Names of all the folded nodes which produce chains. @@ -429,7 +428,6 @@ private: bool &ResNodeDecled, bool isRoot = false) { const CodeGenTarget &T = CGP.getTargetInfo(); unsigned OpNo = (unsigned)N->NodeHasProperty(SDNPHasChain, CGP); - bool HasInFlag = N->NodeHasProperty(SDNPInFlag, CGP); for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) { TreePatternNode *Child = N->getChild(i); if (!Child->isLeaf()) { @@ -480,12 +478,13 @@ private: } } - if (HasInFlag) { + 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) + ");"); } @@ -539,9 +538,6 @@ void PatternCodeEmitter::EmitMatchCode(TreePatternNode *N, TreePatternNode *P, emitCheck(VarMapEntry + " == " + RootName); return; } - - if (!N->isLeaf()) - OperatorMap[N->getName()] = N->getOperator(); } @@ -673,9 +669,8 @@ void PatternCodeEmitter::EmitMatchCode(TreePatternNode *N, TreePatternNode *P, ChainSuffix + utostr(OpNo), FoundChain); } - // Handle cases when root is a complex pattern. - const ComplexPattern *CP; - if (N->isLeaf() && (CP = N->getComplexPatternInfo(CGP))) { + // 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) { @@ -828,19 +823,12 @@ PatternCodeEmitter::EmitResultCode(TreePatternNode *N, if (!N->getName().empty()) { const std::string &VarName = N->getName(); std::string Val = VariableMap[VarName]; - bool ModifiedVal = false; if (Val.empty()) { errs() << "Variable '" << VarName << " referenced but not defined " << "and not caught earlier!\n"; abort(); } - if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') { - // Already selected this operand, just return the tmpval. - NodeOps.push_back(getValueName(Val)); - return NodeOps; - } - const ComplexPattern *CP; unsigned ResNo = TmpNo++; if (!N->isLeaf() && N->getOperator()->getName() == "imm") { assert(N->getExtTypes().size() == 1 && "Multiple types not handled!"); @@ -861,11 +849,7 @@ PatternCodeEmitter::EmitResultCode(TreePatternNode *N, " = CurDAG->getTargetConstant(((" + CastType + ") cast(" + Val + ")->getZExtValue()), " + getEnumName(N->getTypeNum(0)) + ");"); - // Add Tmp to VariableMap, so that we don't multiply select this - // value if used multiple times by this pattern result. - Val = TmpVar; - ModifiedVal = true; - NodeOps.push_back(getValueName(Val)); + 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); @@ -873,53 +857,10 @@ PatternCodeEmitter::EmitResultCode(TreePatternNode *N, " = CurDAG->getTargetConstantFP(*cast(" + Val + ")->getConstantFPValue(), cast(" + Val + ")->getValueType(0));"); - // Add Tmp to VariableMap, so that we don't multiply select this - // value if used multiple times by this pattern result. - Val = TmpVar; - ModifiedVal = true; - NodeOps.push_back(getValueName(Val)); - } else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){ - Record *Op = OperatorMap[N->getName()]; - // Transform ExternalSymbol to TargetExternalSymbol - if (Op && Op->getName() == "externalsym") { - std::string TmpVar = "Tmp"+utostr(ResNo); - emitCode("SDValue " + TmpVar + " = CurDAG->getTarget" - "ExternalSymbol(cast(" + - Val + ")->getSymbol(), " + - getEnumName(N->getTypeNum(0)) + ");"); - // Add Tmp to VariableMap, so that we don't multiply select - // this value if used multiple times by this pattern result. - Val = TmpVar; - ModifiedVal = true; - } - NodeOps.push_back(getValueName(Val)); - } else if (!N->isLeaf() && (N->getOperator()->getName() == "tglobaladdr" - || N->getOperator()->getName() == "tglobaltlsaddr")) { - Record *Op = OperatorMap[N->getName()]; - // Transform GlobalAddress to TargetGlobalAddress - if (Op && (Op->getName() == "globaladdr" || - Op->getName() == "globaltlsaddr")) { - std::string TmpVar = "Tmp" + utostr(ResNo); - emitCode("SDValue " + TmpVar + " = CurDAG->getTarget" - "GlobalAddress(cast(" + Val + - ")->getGlobal(), " + getEnumName(N->getTypeNum(0)) + - ");"); - // Add Tmp to VariableMap, so that we don't multiply select - // this value if used multiple times by this pattern result. - Val = TmpVar; - ModifiedVal = true; - } - NodeOps.push_back(getValueName(Val)); - } else if (!N->isLeaf() - && (N->getOperator()->getName() == "texternalsym" || - N->getOperator()->getName() == "tconstpool")) { - // Do not rewrite the variable name, since we don't generate a new - // temporary. - NodeOps.push_back(getValueName(Val)); - } else if (N->isLeaf() && (CP = N->getComplexPatternInfo(CGP))) { - for (unsigned i = 0; i < CP->getNumOperands(); ++i) { + 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. @@ -931,9 +872,6 @@ PatternCodeEmitter::EmitResultCode(TreePatternNode *N, } NodeOps.push_back(getValueName(Val)); } - - if (ModifiedVal) - VariableMap[VarName] = Val; return NodeOps; } if (N->isLeaf()) { diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index fdefe460a05..eaaaefb3ab7 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -18,15 +18,9 @@ void MatcherNode::dump() const { print(errs()); } -void EmitNodeMatcherNode::print(raw_ostream &OS, unsigned indent) const { - OS.indent(indent) << "EmitNode: Src = " << *Pattern.getSrcPattern() << "\n"; - OS.indent(indent) << "EmitNode: Dst = " << *Pattern.getDstPattern() << "\n"; -} - void MatcherNode::printNext(raw_ostream &OS, unsigned indent) const { if (Next) return Next->print(OS, indent); - OS.indent(indent) << "\n"; } @@ -41,6 +35,16 @@ void RecordMatcherNode::print(raw_ostream &OS, unsigned indent) const { printNext(OS, indent); } +void RecordMemRefMatcherNode::print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "RecordMemRef\n"; + printNext(OS, indent); +} + +void CaptureFlagInputMatcherNode::print(raw_ostream &OS, unsigned indent) const{ + OS.indent(indent) << "CaptureFlagInput\n"; + printNext(OS, indent); +} + void MoveChildMatcherNode::print(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "MoveChild " << ChildNo << '\n'; printNext(OS, indent); @@ -115,17 +119,23 @@ void CheckFoldableChainNodeMatcherNode::print(raw_ostream &OS, void CheckChainCompatibleMatcherNode::print(raw_ostream &OS, unsigned indent) const { - OS.indent(indent) << "CheckChainCompatibleMatcherNode " << PreviousOp << "\n"; + OS.indent(indent) << "CheckChainCompatible " << PreviousOp << "\n"; printNext(OS, indent); } void EmitIntegerMatcherNode::print(raw_ostream &OS, unsigned indent) const { - OS.indent(indent) << "EmitIntegerMatcherNode " << Val << " VT=" << VT << '\n'; + OS.indent(indent) << "EmitInteger " << Val << " VT=" << VT << '\n'; + printNext(OS, indent); +} + +void EmitStringIntegerMatcherNode:: +print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << VT << '\n'; printNext(OS, indent); } void EmitRegisterMatcherNode::print(raw_ostream &OS, unsigned indent) const { - OS.indent(indent) << "EmitRegisterMatcherNode "; + OS.indent(indent) << "EmitRegister "; if (Reg) OS << Reg->getName(); else @@ -134,3 +144,45 @@ void EmitRegisterMatcherNode::print(raw_ostream &OS, unsigned indent) const { printNext(OS, indent); } +void EmitConvertToTargetMatcherNode:: +print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitConvertToTarget " << Slot << '\n'; + printNext(OS, indent); +} + +void EmitMergeInputChainsMatcherNode:: +print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitMergeInputChains \n"; + printNext(OS, indent); +} + +void EmitCopyToRegMatcherNode::print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitCopyToReg \n"; + printNext(OS, indent); +} + +void EmitNodeXFormMatcherNode::print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitNodeXForm " << NodeXForm->getName() + << " Slot=" << Slot << '\n'; + printNext(OS, indent); +} + + +void EmitNodeMatcherNode::print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitNode: " << OpcodeName << ": "; + + for (unsigned i = 0, e = VTs.size(); i != e; ++i) + OS << ' ' << getEnumName(VTs[i]); + OS << '('; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + OS << Operands[i] << ' '; + OS << ")\n"; + printNext(OS, indent); +} + +void PatternMarkerMatcherNode::print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n"; + OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n"; + printNext(OS, indent); +} + diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index 0d5825639d0..4dcb4d6af71 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -13,6 +13,7 @@ #include "llvm/CodeGen/ValueTypes.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" namespace llvm { @@ -37,20 +38,22 @@ class MatcherNode { OwningPtr Next; public: enum KindTy { - // 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. + // Matcher state manipulation. + Push, // Push a checking scope. + RecordNode, // Record the current node. + RecordMemRef, // Record the memref in the current node. + CaptureFlagInput, // If the current node has an input flag, save it. + MoveChild, // Move current node to specified child. + MoveParent, // Move current node to parent. // Predicate checking. - CheckSame, // Fail if not same as prev match. + CheckSame, // Fail if not same as prev match. CheckPatternPredicate, - 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. + 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, @@ -59,9 +62,15 @@ public: CheckChainCompatible, // Node creation/emisssion. - EmitInteger, // Create a TargetConstant - EmitRegister, // Create a register. - EmitNode + EmitInteger, // Create a TargetConstant + EmitStringInteger, // Create a TargetConstant from a string. + EmitRegister, // Create a register. + EmitConvertToTarget, // Convert a imm/fpimm to target imm/fpimm + EmitMergeInputChains, // Merge together a chains for an input. + EmitCopyToReg, // Emit a copytoreg into a physreg. + EmitNode, // Create a DAG node + EmitNodeXForm, // Run a SDNodeXForm + PatternMarker // Comment for printing. }; const KindTy Kind; @@ -124,6 +133,33 @@ public: virtual void print(raw_ostream &OS, unsigned indent = 0) const; }; +/// RecordMemRefMatcherNode - Save the current node's memref. +class RecordMemRefMatcherNode : public MatcherNode { +public: + RecordMemRefMatcherNode() : MatcherNode(RecordMemRef) {} + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == RecordMemRef; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; + + +/// CaptureFlagInputMatcherNode - If the current record has a flag input, record +/// it so that it is used as an input to the generated code. +class CaptureFlagInputMatcherNode : public MatcherNode { +public: + CaptureFlagInputMatcherNode() + : MatcherNode(CaptureFlagInput) {} + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == CaptureFlagInput; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; + /// MoveChildMatcherNode - This tells the interpreter to move into the /// specified child node. class MoveChildMatcherNode : public MatcherNode { @@ -395,6 +431,25 @@ public: virtual void print(raw_ostream &OS, unsigned indent = 0) const; }; + +/// EmitStringIntegerMatcherNode - A target constant whose value is represented +/// by a string. +class EmitStringIntegerMatcherNode : public MatcherNode { + std::string Val; + MVT::SimpleValueType VT; +public: + EmitStringIntegerMatcherNode(const std::string &val, MVT::SimpleValueType vt) + : MatcherNode(EmitStringInteger), Val(val), VT(vt) {} + + const std::string &getValue() const { return Val; } + MVT::SimpleValueType getVT() const { return VT; } + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == EmitStringInteger; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; /// EmitRegisterMatcherNode - This creates a new TargetConstant. class EmitRegisterMatcherNode : public MatcherNode { @@ -415,15 +470,130 @@ public: virtual void print(raw_ostream &OS, unsigned indent = 0) const; }; + +/// EmitConvertToTargetMatcherNode - Emit an operation that reads a specified +/// recorded node and converts it from being a ISD::Constant to +/// ISD::TargetConstant, likewise for ConstantFP. +class EmitConvertToTargetMatcherNode : public MatcherNode { + unsigned Slot; +public: + EmitConvertToTargetMatcherNode(unsigned slot) + : MatcherNode(EmitConvertToTarget), Slot(slot) {} + + unsigned getSlot() const { return Slot; } + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == EmitConvertToTarget; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; + +/// EmitMergeInputChainsMatcherNode - Emit a node that merges a list of input +/// chains together with a token factor. The list of nodes are the nodes in the +/// matched pattern that have chain input/outputs. This node adds all input +/// chains of these nodes if they are not themselves a node in the pattern. +class EmitMergeInputChainsMatcherNode : public MatcherNode { + SmallVector ChainNodes; +public: + EmitMergeInputChainsMatcherNode(const unsigned *nodes, unsigned NumNodes) + : MatcherNode(EmitMergeInputChains), ChainNodes(nodes, nodes+NumNodes) {} + + unsigned getNumNodes() const { return ChainNodes.size(); } + + unsigned getNode(unsigned i) const { + assert(i < ChainNodes.size()); + return ChainNodes[i]; + } + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == EmitMergeInputChains; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; + +/// EmitCopyToRegMatcherNode - Emit a CopyToReg node from a value to a physreg, +/// pushing the chain and flag results. +/// +class EmitCopyToRegMatcherNode : public MatcherNode { + unsigned SrcSlot; // Value to copy into the physreg. + Record *DestPhysReg; +public: + EmitCopyToRegMatcherNode(unsigned srcSlot, Record *destPhysReg) + : MatcherNode(EmitCopyToReg), SrcSlot(srcSlot), DestPhysReg(destPhysReg) {} + + unsigned getSrcSlot() const { return SrcSlot; } + Record *getDestPhysReg() const { return DestPhysReg; } + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == EmitCopyToReg; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; + + + +/// EmitNodeXFormMatcherNode - Emit an operation that runs an SDNodeXForm on a +/// recorded node and records the result. +class EmitNodeXFormMatcherNode : public MatcherNode { + unsigned Slot; + Record *NodeXForm; +public: + EmitNodeXFormMatcherNode(unsigned slot, Record *nodeXForm) + : MatcherNode(EmitNodeXForm), Slot(slot), NodeXForm(nodeXForm) {} + + unsigned getSlot() const { return Slot; } + Record *getNodeXForm() const { return NodeXForm; } + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == EmitNodeXForm; + } + + 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) {} + std::string OpcodeName; + const SmallVector VTs; + const SmallVector Operands; + bool HasChain, HasFlag, HasMemRefs; - const PatternToMatch &getPattern() const { return Pattern; } + /// NumFixedArityOperands - If this is a fixed arity node, this is set to -1. + /// If this is a varidic node, this is set to the number of fixed arity + /// operands in the root of the pattern. The rest are appended to this node. + int NumFixedArityOperands; +public: + EmitNodeMatcherNode(const std::string &opcodeName, + const MVT::SimpleValueType *vts, unsigned numvts, + const unsigned *operands, unsigned numops, + bool hasChain, bool hasFlag, bool hasmemrefs, + int numfixedarityoperands) + : MatcherNode(EmitNode), OpcodeName(opcodeName), + VTs(vts, vts+numvts), Operands(operands, operands+numops), + HasChain(hasChain), HasFlag(hasFlag), HasMemRefs(hasmemrefs), + NumFixedArityOperands(numfixedarityoperands) {} + + const std::string &getOpcodeName() const { return OpcodeName; } + + unsigned getNumVTs() const { return VTs.size(); } + MVT::SimpleValueType getVT(unsigned i) const { + assert(i < VTs.size()); + return VTs[i]; + } + + unsigned getNumOperands() const { return Operands.size(); } + unsigned getOperand(unsigned i) const { + assert(i < Operands.size()); + return Operands[i]; + } + + bool hasChain() const { return HasChain; } + bool hasFlag() const { return HasFlag; } + bool hasMemRefs() const { return HasMemRefs; } + int getNumFixedArityOperands() const { return NumFixedArityOperands; } static inline bool classof(const MatcherNode *N) { return N->getKind() == EmitNode; @@ -431,6 +601,24 @@ public: virtual void print(raw_ostream &OS, unsigned indent = 0) const; }; + +/// PatternMarkerMatcherNode - This prints as a comment indicating the source +/// and dest patterns. +class PatternMarkerMatcherNode : public MatcherNode { + const PatternToMatch &Pattern; +public: + PatternMarkerMatcherNode(const PatternToMatch &pattern) + : MatcherNode(PatternMarker), Pattern(pattern) {} + + const PatternToMatch &getPattern() const { return Pattern; } + + static inline bool classof(const MatcherNode *N) { + return N->getKind() == PatternMarker; + } + + virtual void print(raw_ostream &OS, unsigned indent = 0) const; +}; + } // end namespace llvm diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 4b16db309b2..077dd5df4dd 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -13,6 +13,7 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" +#include "Record.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" @@ -39,7 +40,7 @@ static unsigned EmitInt(int64_t Val, formatted_raw_ostream &OS) { unsigned BytesEmitted = 1; OS << (int)(unsigned char)Val << ", "; if (Val == int8_t(Val)) { - OS << "\n"; + OS << '\n'; return BytesEmitted; } @@ -47,20 +48,21 @@ static unsigned EmitInt(int64_t Val, formatted_raw_ostream &OS) { ++BytesEmitted; if (Val != int16_t(Val)) { - OS << (int)(unsigned char)(Val >> 16) << ',' - << (int)(unsigned char)(Val >> 24) << ','; + OS << (int)(unsigned char)(Val >> 16) << ", " + << (int)(unsigned char)(Val >> 24) << ", "; BytesEmitted += 2; if (Val != int32_t(Val)) { - OS << (int)(unsigned char)(Val >> 32) << ',' - << (int)(unsigned char)(Val >> 40) << ',' - << (int)(unsigned char)(Val >> 48) << ',' - << (int)(unsigned char)(Val >> 56) << ','; + OS << (int)(unsigned char)(Val >> 32) << ", " + << (int)(unsigned char)(Val >> 40) << ", " + << (int)(unsigned char)(Val >> 48) << ", " + << (int)(unsigned char)(Val >> 56) << ", "; BytesEmitted += 4; } } - OS.PadToColumn(CommentIndent) << "// " << Val << '\n'; + OS.PadToColumn(CommentIndent) << "// " << Val << " aka 0x"; + OS.write_hex(Val) << '\n'; return BytesEmitted; } @@ -73,6 +75,11 @@ class MatcherTableEmitter { DenseMap ComplexPatternMap; std::vector ComplexPatterns; + + + DenseMap NodeXFormMap; + std::vector NodeXForms; + public: MatcherTableEmitter(formatted_raw_ostream &os) : OS(os) {} @@ -107,6 +114,16 @@ private: } return Entry-1; } + + unsigned getNodeXFormID(Record *Rec) { + unsigned &Entry = NodeXFormMap[Rec]; + if (Entry == 0) { + NodeXForms.push_back(Rec); + Entry = NodeXForms.size(); + } + return Entry-1; + } + }; } // end anonymous namespace. @@ -118,18 +135,20 @@ EmitMatcher(const MatcherNode *N, unsigned Indent) { switch (N->getKind()) { case MatcherNode::Push: assert(0 && "Should be handled by caller"); - case MatcherNode::EmitNode: - OS << "// Src: " - << *cast(N)->getPattern().getSrcPattern() << '\n'; - OS.PadToColumn(Indent*2) << "// Dst: " - << *cast(N)->getPattern().getDstPattern() << "\n"; - OS.PadToColumn(Indent*2) << "OPC_Emit, /*XXX*/\n\n"; - return 1; case MatcherNode::RecordNode: OS << "OPC_RecordNode,"; OS.PadToColumn(CommentIndent) << "// " << cast(N)->getWhatFor() << '\n'; return 1; + + case MatcherNode::RecordMemRef: + OS << "OPC_RecordMemRef,\n"; + return 1; + + case MatcherNode::CaptureFlagInput: + OS << "OPC_CaptureFlagInput,\n"; + return 1; + case MatcherNode::MoveChild: OS << "OPC_MoveChild, " << cast(N)->getChildNo() << ",\n"; @@ -219,6 +238,14 @@ EmitMatcher(const MatcherNode *N, unsigned Indent) { << getEnumName(cast(N)->getVT()) << ", "; return EmitInt(Val, OS)+2; } + case MatcherNode::EmitStringInteger: { + const std::string &Val = cast(N)->getValue(); + // These should always fit into one byte. + OS << "OPC_EmitInteger1, " + << getEnumName(cast(N)->getVT()) << ", " + << Val << ",\n"; + return 3; + } case MatcherNode::EmitRegister: OS << "OPC_EmitRegister, " @@ -228,6 +255,62 @@ EmitMatcher(const MatcherNode *N, unsigned Indent) { else OS << "0 /*zero_reg*/,\n"; return 3; + + case MatcherNode::EmitConvertToTarget: + OS << "OPC_EmitConvertToTarget, " + << cast(N)->getSlot() << ",\n"; + return 2; + + case MatcherNode::EmitMergeInputChains: { + const EmitMergeInputChainsMatcherNode *MN = + cast(N); + OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", "; + for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i) + OS << MN->getNode(i) << ", "; + OS << '\n'; + return 2+MN->getNumNodes(); + } + case MatcherNode::EmitCopyToReg: + OS << "OPC_EmitCopyToReg, " + << cast(N)->getSrcSlot() << ", " + << getQualifiedName(cast(N)->getDestPhysReg()) + << ",\n"; + return 3; + case MatcherNode::EmitNodeXForm: { + const EmitNodeXFormMatcherNode *XF = cast(N); + OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", " + << XF->getSlot() << ','; + OS.PadToColumn(CommentIndent) << "// "<getNodeXForm()->getName()<<'\n'; + return 3; + } + + case MatcherNode::EmitNode: { + const EmitNodeMatcherNode *EN = cast(N); + OS << "OPC_EmitNode, TARGET_OPCODE(" << EN->getOpcodeName() << "), 0"; + + if (EN->hasChain()) OS << "|OPFL_Chain"; + if (EN->hasFlag()) OS << "|OPFL_Flag"; + if (EN->hasMemRefs()) OS << "|OPFL_MemRefs"; + if (EN->getNumFixedArityOperands() != -1) + OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands(); + OS << ",\n"; + + OS.PadToColumn(Indent*2+4) << EN->getNumVTs() << "/*#VTs*/, "; + for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i) + OS << getEnumName(EN->getVT(i)) << ", "; + + OS << EN->getNumOperands() << "/*#Ops*/, "; + for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i) + OS << EN->getOperand(i) << ", "; + OS << '\n'; + return 5+EN->getNumVTs()+EN->getNumOperands(); + } + case MatcherNode::PatternMarker: + OS << "// Src: " + << *cast(N)->getPattern().getSrcPattern() << '\n'; + OS.PadToColumn(Indent*2) << "// Dst: " + << *cast(N)->getPattern().getDstPattern() << '\n'; + return 0; } assert(0 && "Unreachable"); return 0; @@ -255,7 +338,7 @@ EmitMatcherList(const MatcherNode *N, unsigned Indent) { if (NextSize > 255) { errs() << "Tblgen internal error: can't handle predicate this complex yet\n"; - exit(1); + // FIXME: exit(1); } OS.PadToColumn(Indent*2); @@ -300,6 +383,7 @@ void MatcherTableEmitter::EmitPredicateFunctions() { OS << "}\n\n"; // Emit CompletePattern matchers. + // FIXME: This should be const. OS << "bool CheckComplexPattern(SDNode *Root, SDValue N,\n"; OS << " unsigned PatternNo, SmallVectorImpl &Result) {\n"; OS << " switch (PatternNo) {\n"; @@ -307,17 +391,38 @@ void MatcherTableEmitter::EmitPredicateFunctions() { for (unsigned i = 0, e = ComplexPatterns.size(); i != e; ++i) { const ComplexPattern &P = *ComplexPatterns[i]; unsigned NumOps = P.getNumOperands(); + if (P.hasProperty(SDNPHasChain)) - NumOps += 2; // Input and output chains. + ++NumOps; // Get the chained node too. + OS << " case " << i << ":\n"; OS << " Result.resize(Result.size()+" << NumOps << ");\n"; - OS << " return " << P.getSelectFunc() << "(Root, N"; + OS << " return " << P.getSelectFunc(); + + // FIXME: Temporary hack until old isel dies. + if (P.hasProperty(SDNPHasChain)) + OS << "XXX"; + + OS << "(Root, N"; for (unsigned i = 0; i != NumOps; ++i) OS << ", Result[Result.size()-" << (NumOps-i) << ']'; OS << ");\n"; } OS << " }\n"; OS << "}\n\n"; + + // Emit SDNodeXForm handlers. + // FIXME: This should be const. + OS << "SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) {\n"; + OS << " switch (XFormNo) {\n"; + OS << " default: assert(0 && \"Invalid xform # in table?\");\n"; + + // FIXME: The node xform could take SDValue's instead of SDNode*'s. + for (unsigned i = 0, e = NodeXForms.size(); i != e; ++i) + OS << " case " << i << ": return Transform_" << NodeXForms[i]->getName() + << "(V.getNode());\n"; + OS << " }\n"; + OS << "}\n\n"; } @@ -329,9 +434,12 @@ void llvm::EmitMatcherTable(const MatcherNode *Matcher, raw_ostream &O) { MatcherTableEmitter MatcherEmitter(OS); + OS << " // Opcodes are emitted as 2 bytes, TARGET_OPCODE handles this.\n"; + OS << " #define TARGET_OPCODE(X) X & 255, unsigned(X) >> 8\n"; OS << " static const unsigned char MatcherTable[] = {\n"; unsigned TotalSize = MatcherEmitter.EmitMatcherList(Matcher, 2); OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n"; + OS << " #undef TARGET_OPCODE\n"; OS << " return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n"; OS << "\n"; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index d87f7378161..693c4ccf8d3 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -12,29 +12,42 @@ #include "Record.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include using namespace llvm; -namespace { - /// ResultVal - When generating new nodes for the result of a pattern match, - /// this value is used to represent an input to the node. Result values can - /// either be an input that is 'recorded' in the RecordedNodes array by the - /// matcher or it can be a temporary value created by the emitter for things - /// like constants. - class ResultVal { - unsigned Number; - public: - static ResultVal get(unsigned N) { - ResultVal R; - R.Number = N; - return R; - } - unsigned getNumber() const { - return Number; +/// 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 &RCs = T.getRegisterClasses(); + std::vector::const_iterator Element; + + for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) { + const CodeGenRegisterClass &RC = RCs[rc]; + if (!std::count(RC.Elements.begin(), RC.Elements.end(), R)) + continue; + + if (!FoundRC) { + FoundRC = true; + VT = RC.getValueTypeNum(0); + continue; } - }; - - + + // In multiple RC's. If the Types of the RC's do not agree, return + // MVT::Other. The target is responsible for handling this. + if (VT != RC.getValueTypeNum(0)) + // FIXME2: when does this happen? Abort? + return MVT::Other; + } + return VT; +} + + +namespace { class MatcherGen { const PatternToMatch &Pattern; const CodeGenDAGPatterns &CGP; @@ -54,9 +67,18 @@ namespace { /// record into. unsigned NextRecordedOperandNo; - /// InputChains - This maintains the position in the recorded nodes array of - /// all of the recorded input chains. - SmallVector InputChains; + /// MatchedChainNodes - This maintains the position in the recorded nodes + /// array of all of the recorded input nodes that have chains. + SmallVector MatchedChainNodes; + + /// PhysRegInputs - List list has an entry for each explicitly specified + /// physreg input to the pattern. The first elt is the Register node, the + /// second is the recorded slot number the input pattern match saved it in. + SmallVector, 2> PhysRegInputs; + + /// EmittedMergeInputChains - For nodes that match patterns involving + /// chains, is set to true if we emitted the "MergeInputChains" operation. + bool EmittedMergeInputChains; /// Matcher - This is the top level of the generated matcher, the result. MatcherNode *Matcher; @@ -87,20 +109,35 @@ namespace { TreePatternNode *NodeNoTypes); // Result Code Generation. + unsigned getNamedArgumentSlot(StringRef Name) { + unsigned VarMapEntry = VariableMap[Name]; + assert(VarMapEntry != 0 && + "Variable referenced but not defined and not caught earlier!"); + return VarMapEntry-1; + } + + /// GetInstPatternNode - Get the pattern for an instruction. + const TreePatternNode *GetInstPatternNode(const DAGInstruction &Ins, + const TreePatternNode *N); + void EmitResultOperand(const TreePatternNode *N, - SmallVectorImpl &ResultOps); + SmallVectorImpl &ResultOps); + void EmitResultOfNamedOperand(const TreePatternNode *N, + SmallVectorImpl &ResultOps); void EmitResultLeafAsOperand(const TreePatternNode *N, - SmallVectorImpl &ResultOps); + SmallVectorImpl &ResultOps); void EmitResultInstructionAsOperand(const TreePatternNode *N, - SmallVectorImpl &ResultOps); - }; + SmallVectorImpl &ResultOps); + void EmitResultSDNodeXFormAsOperand(const TreePatternNode *N, + SmallVectorImpl &ResultOps); + }; } // end anon namespace. MatcherGen::MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp) : Pattern(pattern), CGP(cgp), NextRecordedOperandNo(0), - Matcher(0), CurPredicate(0) { + EmittedMergeInputChains(false), Matcher(0), CurPredicate(0) { // We need to produce the matcher tree for the patterns source pattern. To do // this we need to match the structure as well as the types. To do the type // matching, we want to figure out the fewest number of type checks we need to @@ -158,6 +195,11 @@ void MatcherGen::AddMatcherNode(MatcherNode *NewNode) { /// EmitLeafMatchCode - Generate matching code for leaf nodes. void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { assert(N->isLeaf() && "Not a leaf?"); + + // If there are node predicates for this node, generate their checks. + for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i) + AddMatcherNode(new CheckPredicateMatcherNode(N->getPredicateFns()[i])); + // Direct match against an integer constant. if (IntInit *II = dynamic_cast(N->getLeafValue())) return AddMatcherNode(new CheckIntegerMatcherNode(II->getValue())); @@ -172,10 +214,17 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { if (// Handle register references. Nothing to do here, they always match. LeafRec->isSubClassOf("RegisterClass") || LeafRec->isSubClassOf("PointerLikeRegClass") || - LeafRec->isSubClassOf("Register") || // Place holder for SRCVALUE nodes. Nothing to do here. LeafRec->getName() == "srcvalue") return; + + // If we have a physreg reference like (mul gpr:$src, EAX) then we need to + // record the register + if (LeafRec->isSubClassOf("Register")) { + AddMatcherNode(new RecordMatcherNode("physreg input "+LeafRec->getName())); + PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++)); + return; + } if (LeafRec->isSubClassOf("ValueType")) return AddMatcherNode(new CheckValueTypeMatcherNode(LeafRec->getName())); @@ -202,15 +251,15 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { // It is the last operand recorded. assert(NextRecordedOperandNo > 1 && "Should have recorded input/result chains at least!"); - InputChains.push_back(NextRecordedOperandNo-1); + MatchedChainNodes.push_back(NextRecordedOperandNo-1); - // IF we need to check chains, do so, see comment for + // 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, + if (MatchedChainNodes.size() > 1) { + // FIXME2: 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]; + unsigned PrevOp = MatchedChainNodes[MatchedChainNodes.size()-2]; AddMatcherNode(new CheckChainCompatibleMatcherNode(PrevOp)); } } @@ -238,7 +287,8 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, // to handle this. if ((N->getOperator()->getName() == "and" || N->getOperator()->getName() == "or") && - N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty()) { + N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty() && + N->getPredicateFns().empty()) { if (IntInit *II = dynamic_cast(N->getChild(1)->getLeafValue())) { if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits. if (N->getOperator()->getName() == "and") @@ -258,30 +308,36 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, // Check that the current opcode lines up. AddMatcherNode(new CheckOpcodeMatcherNode(CInfo.getEnumName())); + // If there are node predicates for this node, generate their checks. + for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i) + AddMatcherNode(new CheckPredicateMatcherNode(N->getPredicateFns()[i])); + + + // If this node has memory references (i.e. is a load or store), tell the + // interpreter to capture them in the memref array. + if (N->NodeHasProperty(SDNPMemOperand, CGP)) + AddMatcherNode(new RecordMemRefMatcherNode()); + // If this node has a chain, then the chain is operand #0 is the SDNode, and // the child numbers of the node are all offset by one. unsigned OpNo = 0; if (N->NodeHasProperty(SDNPHasChain, CGP)) { - // Record the input chain, which is always input #0 of the SDNode. - AddMatcherNode(new MoveChildMatcherNode(0)); + // Record the node and remember it in our chained nodes list. AddMatcherNode(new RecordMatcherNode("'" + N->getOperator()->getName() + - "' input chain")); - + "' chained node")); // Remember all of the input chains our pattern will match. - InputChains.push_back(NextRecordedOperandNo); - ++NextRecordedOperandNo; - AddMatcherNode(new MoveParentMatcherNode()); + MatchedChainNodes.push_back(NextRecordedOperandNo++); // If this is the second (e.g. indbr(load) or store(add(load))) or third // input chain (e.g. (store (add (load, load))) from msp430) we need to make // 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. - if (InputChains.size() > 1) { - // FIXME: This is broken, we should eliminate this nonsense completely, + if (MatchedChainNodes.size() > 1) { + // FIXME2: 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]; + unsigned PrevOp = MatchedChainNodes[MatchedChainNodes.size()-2]; AddMatcherNode(new CheckChainCompatibleMatcherNode(PrevOp)); } @@ -336,6 +392,12 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, AddMatcherNode(new CheckFoldableChainNodeMatcherNode()); } } + + // If this node is known to have an input flag or if it *might* have an input + // flag, capture it as the flag input of the pattern. + if (N->NodeHasProperty(SDNPOptInFlag, CGP) || + N->NodeHasProperty(SDNPInFlag, CGP)) + AddMatcherNode(new CaptureFlagInputMatcherNode()); for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) { // Get the code suitable for matching this child. Move to the child, check @@ -370,12 +432,12 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, // If this is a complex pattern, the match operation for it will // implicitly record all of the outputs of it (which may be more than // one). - if (const ComplexPattern *AM = N->getComplexPatternInfo(CGP)) { + if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) { // Record the right number of operands. - NumRecorded = AM->getNumOperands()-1; + NumRecorded = CP->getNumOperands(); - if (AM->hasProperty(SDNPHasChain)) - NumRecorded += 2; // Input and output chains. + if (CP->hasProperty(SDNPHasChain)) + ++NumRecorded; // Chained node operand. } else { // If it is a normal named node, we must emit a 'Record' opcode. AddMatcherNode(new RecordMatcherNode("$" + N->getName())); @@ -393,10 +455,6 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, } } - // If there are node predicates for this node, generate their checks. - for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i) - AddMatcherNode(new CheckPredicateMatcherNode(N->getPredicateFns()[i])); - if (N->isLeaf()) EmitLeafMatchCode(N); else @@ -419,13 +477,42 @@ void MatcherGen::EmitMatcherCode() { // Node Result Generation //===----------------------------------------------------------------------===// +void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, + SmallVectorImpl &ResultOps){ + assert(!N->getName().empty() && "Operand not named!"); + + unsigned SlotNo = getNamedArgumentSlot(N->getName()); + + // A reference to a complex pattern gets all of the results of the complex + // pattern's match. + if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) { + for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) + ResultOps.push_back(SlotNo+i); + return; + } + + // If this is an 'imm' or 'fpimm' node, make sure to convert it to the target + // version of the immediate so that it doesn't get selected due to some other + // node use. + if (!N->isLeaf()) { + StringRef OperatorName = N->getOperator()->getName(); + if (OperatorName == "imm" || OperatorName == "fpimm") { + AddMatcherNode(new EmitConvertToTargetMatcherNode(SlotNo)); + ResultOps.push_back(NextRecordedOperandNo++); + return; + } + } + + ResultOps.push_back(SlotNo); +} + void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, - SmallVectorImpl &ResultOps){ + 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(ResultVal::get(NextRecordedOperandNo++)); + ResultOps.push_back(NextRecordedOperandNo++); return; } @@ -434,53 +521,97 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, if (DI->getDef()->isSubClassOf("Register")) { AddMatcherNode(new EmitRegisterMatcherNode(DI->getDef(), N->getTypeNum(0))); - ResultOps.push_back(ResultVal::get(NextRecordedOperandNo++)); + ResultOps.push_back(NextRecordedOperandNo++); return; } if (DI->getDef()->getName() == "zero_reg") { AddMatcherNode(new EmitRegisterMatcherNode(0, N->getTypeNum(0))); - ResultOps.push_back(ResultVal::get(NextRecordedOperandNo++)); + ResultOps.push_back(NextRecordedOperandNo++); return; } -#if 0 + // Handle a reference to a register class. This is used + // in COPY_TO_SUBREG instructions. if (DI->getDef()->isSubClassOf("RegisterClass")) { - // Handle a reference to a register class. This is used - // in COPY_TO_SUBREG instructions. - // FIXME: Implement. + std::string Value = getQualifiedName(DI->getDef()) + "RegClassID"; + AddMatcherNode(new EmitStringIntegerMatcherNode(Value, N->getTypeNum(0))); + ResultOps.push_back(NextRecordedOperandNo++); + return; } -#endif } errs() << "unhandled leaf node: \n"; N->dump(); } -void MatcherGen::EmitResultInstructionAsOperand(const TreePatternNode *N, - SmallVectorImpl &ResultOps){ +/// GetInstPatternNode - Get the pattern for an instruction. +/// +const TreePatternNode *MatcherGen:: +GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) { + const TreePattern *InstPat = Inst.getPattern(); + + // FIXME2?: Assume actual pattern comes before "implicit". + TreePatternNode *InstPatNode; + if (InstPat) + InstPatNode = InstPat->getTree(0); + else if (/*isRoot*/ N == Pattern.getDstPattern()) + InstPatNode = Pattern.getSrcPattern(); + else + return 0; + + if (InstPatNode && !InstPatNode->isLeaf() && + InstPatNode->getOperator()->getName() == "set") + InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1); + + return InstPatNode; +} + +void MatcherGen:: +EmitResultInstructionAsOperand(const TreePatternNode *N, + SmallVectorImpl &OutputOps) { Record *Op = N->getOperator(); const CodeGenTarget &CGT = CGP.getTargetInfo(); CodeGenInstruction &II = CGT.getInstruction(Op->getName()); const DAGInstruction &Inst = CGP.getInstruction(Op); - // FIXME: Handle (set x, (foo)) + // If we can, get the pattern for the instruction we're generating. We derive + // a variety of information from this pattern, such as whether it has a chain. + // + // FIXME2: This is extremely dubious for several reasons, not the least of + // which it gives special status to instructions with patterns that Pat<> + // nodes can't duplicate. + const TreePatternNode *InstPatNode = GetInstPatternNode(Inst, N); + + // NodeHasChain - Whether the instruction node we're creating takes chains. + bool NodeHasChain = InstPatNode && + InstPatNode->TreeHasProperty(SDNPHasChain, CGP); - if (II.isVariadic) // FIXME: Handle variadic instructions. - return AddMatcherNode(new EmitNodeMatcherNode(Pattern)); - - // FIXME: Handle OptInFlag, HasInFlag, HasOutFlag - // FIXME: Handle Chains. + bool isRoot = N == Pattern.getDstPattern(); + + // NodeHasOutFlag - True if this node has a flag. + bool NodeHasInFlag = false, NodeHasOutFlag = false; + if (isRoot) { + const TreePatternNode *SrcPat = Pattern.getSrcPattern(); + NodeHasInFlag = SrcPat->TreeHasProperty(SDNPOptInFlag, CGP) || + SrcPat->TreeHasProperty(SDNPInFlag, CGP); + + // FIXME2: this is checking the entire pattern, not just the node in + // question, doing this just for the root seems like a total hack. + NodeHasOutFlag = SrcPat->TreeHasProperty(SDNPOutFlag, CGP); + } + + // NumResults - This is the number of results produced by the instruction in + // the "outs" list. unsigned NumResults = Inst.getNumResults(); - // 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 instruction. However, in cases // where there are predicate operands for an instruction, we need to fill // in the 'execute always' values. Match up the node operands to the // instruction operands to do this. - SmallVector Ops; + SmallVector InstOps; for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.OperandList.size(); InstOpNo != e; ++InstOpNo) { @@ -494,32 +625,137 @@ void MatcherGen::EmitResultInstructionAsOperand(const TreePatternNode *N, const DAGDefaultOperand &DefaultOp = CGP.getDefaultOperand(II.OperandList[InstOpNo].Rec); for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i) - EmitResultOperand(DefaultOp.DefaultOps[i], Ops); + EmitResultOperand(DefaultOp.DefaultOps[i], InstOps); continue; } // Otherwise this is a normal operand or a predicate operand without // 'execute always'; emit it. - EmitResultOperand(N->getChild(ChildNo), Ops); + EmitResultOperand(N->getChild(ChildNo), InstOps); ++ChildNo; } - // FIXME: Chain. - // FIXME: Flag + // Nodes that match patterns with (potentially multiple) chain inputs have to + // merge them together into a token factor. + if (NodeHasChain && !EmittedMergeInputChains) { + // FIXME2: Move this out of emitresult to a top level place. + assert(!MatchedChainNodes.empty() && + "How can this node have chain if no inputs do?"); + // Otherwise, we have to emit an operation to merge the input chains and + // set this as the current input chain. + AddMatcherNode(new EmitMergeInputChainsMatcherNode + (MatchedChainNodes.data(), MatchedChainNodes.size())); + EmittedMergeInputChains = true; + } + + // If this node has an input flag or explicitly specified input physregs, we + // need to add chained and flagged copyfromreg nodes and materialize the flag + // input. + if (isRoot && !PhysRegInputs.empty()) { + // Emit all of the CopyToReg nodes for the input physical registers. These + // occur in patterns like (mul:i8 AL:i8, GR8:i8:$src). + for (unsigned i = 0, e = PhysRegInputs.size(); i != e; ++i) + AddMatcherNode(new EmitCopyToRegMatcherNode(PhysRegInputs[i].second, + PhysRegInputs[i].first)); + // Even if the node has no other flag inputs, the resultant node must be + // flagged to the CopyFromReg nodes we just generated. + NodeHasInFlag = true; + } + + // Result order: node results, chain, flags + + // Determine the result types. + SmallVector ResultVTs; + if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid) { + // FIXME2: If the node has multiple results, we should add them. For now, + // preserve existing behavior?! + ResultVTs.push_back(N->getTypeNum(0)); + } + + + // If this is the root instruction of a pattern that has physical registers in + // its result pattern, add output VTs for them. For example, X86 has: + // (set AL, (mul ...)) + // This also handles implicit results like: + // (implicit EFLAGS) + if (isRoot && Pattern.getDstRegs().size() != 0) { + for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) + if (Pattern.getDstRegs()[i]->isSubClassOf("Register")) + ResultVTs.push_back(getRegisterValueType(Pattern.getDstRegs()[i], CGT)); + } + if (NodeHasChain) + ResultVTs.push_back(MVT::Other); + if (NodeHasOutFlag) + ResultVTs.push_back(MVT::Flag); + + // FIXME2: Instead of using the isVariadic flag on the instruction, we should + // have an SDNP that indicates variadicism. The TargetInstrInfo isVariadic + // property should be inferred from this when an instruction has a pattern. + int NumFixedArityOperands = -1; + if (isRoot && II.isVariadic) + NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren(); + + // If this is the root node and any of the nodes matched nodes in the input + // pattern have MemRefs in them, have the interpreter collect them and plop + // them onto this node. + // + // FIXME3: This is actively incorrect for result patterns where the root of + // the pattern is not the memory reference and is also incorrect when the + // result pattern has multiple memory-referencing instructions. For example, + // in the X86 backend, this pattern causes the memrefs to get attached to the + // CVTSS2SDrr instead of the MOVSSrm: + // + // def : Pat<(extloadf32 addr:$src), + // (CVTSS2SDrr (MOVSSrm addr:$src))>; + // + bool NodeHasMemRefs = + isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP); + + // FIXME: Eventually add a SelectNodeTo form. It works if the new node has a + // superset of the results of the old node, in the same places. E.g. turning + // (add (load)) -> add32rm is ok because result #0 is the result and result #1 + // is new. + AddMatcherNode(new EmitNodeMatcherNode(II.Namespace+"::"+II.TheDef->getName(), + ResultVTs.data(), ResultVTs.size(), + InstOps.data(), InstOps.size(), + NodeHasChain, NodeHasInFlag, + NodeHasMemRefs,NumFixedArityOperands)); + + // The newly emitted node gets recorded. + // FIXME2: This should record all of the results except the (implicit) one. + OutputOps.push_back(NextRecordedOperandNo++); + // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode + // variants. Call MorphNodeTo instead of SelectNodeTo. +} + +void MatcherGen:: +EmitResultSDNodeXFormAsOperand(const TreePatternNode *N, + SmallVectorImpl &ResultOps) { + assert(N->getOperator()->isSubClassOf("SDNodeXForm") && "Not SDNodeXForm?"); + + // Emit the operand. + SmallVector InputOps; - return; + // FIXME2: Could easily generalize this to support multiple inputs and outputs + // to the SDNodeXForm. For now we just support one input and one output like + // the old instruction selector. + assert(N->getNumChildren() == 1); + EmitResultOperand(N->getChild(0), InputOps); + + // The input currently must have produced exactly one result. + assert(InputOps.size() == 1 && "Unexpected input to SDNodeXForm"); + + AddMatcherNode(new EmitNodeXFormMatcherNode(InputOps[0], N->getOperator())); + ResultOps.push_back(NextRecordedOperandNo++); } void MatcherGen::EmitResultOperand(const TreePatternNode *N, - SmallVectorImpl &ResultOps) { + SmallVectorImpl &ResultOps) { // This is something selected from the pattern we matched. - if (!N->getName().empty()) { - //errs() << "unhandled named node: \n"; - //N->dump(); - return; - } + if (!N->getName().empty()) + return EmitResultOfNamedOperand(N, ResultOps); if (N->isLeaf()) return EmitResultLeafAsOperand(N, ResultOps); @@ -528,19 +764,23 @@ void MatcherGen::EmitResultOperand(const TreePatternNode *N, if (OpRec->isSubClassOf("Instruction")) return EmitResultInstructionAsOperand(N, ResultOps); if (OpRec->isSubClassOf("SDNodeXForm")) - // FIXME: implement. - return; + return EmitResultSDNodeXFormAsOperand(N, ResultOps); errs() << "Unknown result node to emit code for: " << *N << '\n'; throw std::string("Unknown node in result pattern!"); } void MatcherGen::EmitResultCode() { - // FIXME: Handle Ops. - // FIXME: Ops should be vector of "ResultValue> which is either an index into - // the results vector is is a temp result. - SmallVector Ops; + SmallVector Ops; EmitResultOperand(Pattern.getDstPattern(), Ops); - //AddMatcherNode(new EmitNodeMatcherNode(Pattern)); + + // We know that the resulting pattern has exactly one result/ + // FIXME2: why? what about something like (set a,b,c, (complexpat)) + // FIXME2: Implicit results should be pushed here I guess? + assert(Ops.size() == 1); + // FIXME: Handle Ops. + // FIXME: Handle (set EAX, (foo)) but not (implicit EFLAGS) + + AddMatcherNode(new PatternMarkerMatcherNode(Pattern)); } @@ -551,6 +791,12 @@ MatcherNode *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern, // Generate the code for the matcher. Gen.EmitMatcherCode(); + + // FIXME2: Kill extra MoveParent commands at the end of the matcher sequence. + // FIXME2: Split result code out to another table, and make the matcher end + // with an "Emit " command. This allows result generation stuff to be + // shared and factored? + // If the match succeeds, then we generate Pattern. Gen.EmitResultCode();