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,
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;
/// 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;
}
assert(!NodeToMatch->isMachineOpcode() && "Node already selected!");
-
+
+ // Set up the node stack with NodeToMatch as the only node on the stack.
+ SmallVector<SDValue, 8> 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<MatchScope, 8> MatchScopes;
// RecordedNodes - This is the set of nodes that have been recorded by the
// state machine.
SmallVector<SDValue, 8> RecordedNodes;
- // Set up the node stack with NodeToMatch as the only node on the stack.
- SmallVector<SDValue, 8> 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<MachineMemOperand*, 2> 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<SDNode*, 3> 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;
}
// 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<MemSDNode>(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++];
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++];
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<ConstantSDNode>(Imm)->getZExtValue();
+ Imm = CurDAG->getTargetConstant(Val, Imm.getValueType());
+ } else if (Imm->getOpcode() == ISD::ConstantFP) {
+ const ConstantFP *Val=cast<ConstantFPSDNode>(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<SDValue, 3> 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<EVT, 4> 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<SDValue, 8> 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
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();
}
}
/// 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<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
// Node to name mapping
std::map<std::string, std::string> VariableMap;
- // Node to operator mapping
- std::map<std::string, Record*> OperatorMap;
// Name of the folded node which produces a flag.
std::pair<std::string, unsigned> FoldedFlag;
// Names of all the folded nodes which produce chains.
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()) {
}
}
- 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) + ");");
}
emitCheck(VarMapEntry + " == " + RootName);
return;
}
-
- if (!N->isLeaf())
- OperatorMap[N->getName()] = N->getOperator();
}
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) {
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!");
" = CurDAG->getTargetConstant(((" + CastType +
") cast<ConstantSDNode>(" + Val + ")->getZExtValue()), " +
getEnumName(N->getTypeNum(0)) + ");");
- // Add Tmp<ResNo> 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);
" = CurDAG->getTargetConstantFP(*cast<ConstantFPSDNode>(" +
Val + ")->getConstantFPValue(), cast<ConstantFPSDNode>(" +
Val + ")->getValueType(0));");
- // Add Tmp<ResNo> 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<ExternalSymbolSDNode>(" +
- Val + ")->getSymbol(), " +
- getEnumName(N->getTypeNum(0)) + ");");
- // Add Tmp<ResNo> 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<GlobalAddressSDNode>(" + Val +
- ")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
- ");");
- // Add Tmp<ResNo> 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.
}
NodeOps.push_back(getValueName(Val));
}
-
- if (ModifiedVal)
- VariableMap[VarName] = Val;
return NodeOps;
}
if (N->isLeaf()) {
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) << "<null next field>\n";
}
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);
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
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 <todo: args>\n";
+ printNext(OS, indent);
+}
+
+void EmitCopyToRegMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitCopyToReg <todo: args>\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 << ": <todo flags> ";
+
+ 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);
+}
+
#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 {
OwningPtr<MatcherNode> 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,
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;
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 {
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 {
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<unsigned, 3> 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 {
+ std::string OpcodeName;
+ const SmallVector<MVT::SimpleValueType, 3> VTs;
+ const SmallVector<unsigned, 6> Operands;
+ bool HasChain, HasFlag, HasMemRefs;
+
+ /// 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;
+ }
+
+ 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:
- EmitNodeMatcherNode(const PatternToMatch &pattern)
- : MatcherNode(EmitNode), Pattern(pattern) {}
+ PatternMarkerMatcherNode(const PatternToMatch &pattern)
+ : MatcherNode(PatternMarker), Pattern(pattern) {}
const PatternToMatch &getPattern() const { return Pattern; }
static inline bool classof(const MatcherNode *N) {
- return N->getKind() == EmitNode;
+ return N->getKind() == PatternMarker;
}
virtual void print(raw_ostream &OS, unsigned indent = 0) const;
};
+
} // end namespace llvm
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
+#include "Record.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
unsigned BytesEmitted = 1;
OS << (int)(unsigned char)Val << ", ";
if (Val == int8_t(Val)) {
- OS << "\n";
+ OS << '\n';
return BytesEmitted;
}
++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;
}
DenseMap<const ComplexPattern*, unsigned> ComplexPatternMap;
std::vector<const ComplexPattern*> ComplexPatterns;
+
+
+ DenseMap<Record*, unsigned> NodeXFormMap;
+ std::vector<const Record*> NodeXForms;
+
public:
MatcherTableEmitter(formatted_raw_ostream &os) : OS(os) {}
}
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.
switch (N->getKind()) {
case MatcherNode::Push: assert(0 && "Should be handled by caller");
- case MatcherNode::EmitNode:
- OS << "// Src: "
- << *cast<EmitNodeMatcherNode>(N)->getPattern().getSrcPattern() << '\n';
- OS.PadToColumn(Indent*2) << "// Dst: "
- << *cast<EmitNodeMatcherNode>(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<RecordMatcherNode>(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<MoveChildMatcherNode>(N)->getChildNo() << ",\n";
<< getEnumName(cast<EmitIntegerMatcherNode>(N)->getVT()) << ", ";
return EmitInt(Val, OS)+2;
}
+ case MatcherNode::EmitStringInteger: {
+ const std::string &Val = cast<EmitStringIntegerMatcherNode>(N)->getValue();
+ // These should always fit into one byte.
+ OS << "OPC_EmitInteger1, "
+ << getEnumName(cast<EmitStringIntegerMatcherNode>(N)->getVT()) << ", "
+ << Val << ",\n";
+ return 3;
+ }
case MatcherNode::EmitRegister:
OS << "OPC_EmitRegister, "
else
OS << "0 /*zero_reg*/,\n";
return 3;
+
+ case MatcherNode::EmitConvertToTarget:
+ OS << "OPC_EmitConvertToTarget, "
+ << cast<EmitConvertToTargetMatcherNode>(N)->getSlot() << ",\n";
+ return 2;
+
+ case MatcherNode::EmitMergeInputChains: {
+ const EmitMergeInputChainsMatcherNode *MN =
+ cast<EmitMergeInputChainsMatcherNode>(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<EmitCopyToRegMatcherNode>(N)->getSrcSlot() << ", "
+ << getQualifiedName(cast<EmitCopyToRegMatcherNode>(N)->getDestPhysReg())
+ << ",\n";
+ return 3;
+ case MatcherNode::EmitNodeXForm: {
+ const EmitNodeXFormMatcherNode *XF = cast<EmitNodeXFormMatcherNode>(N);
+ OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", "
+ << XF->getSlot() << ',';
+ OS.PadToColumn(CommentIndent) << "// "<<XF->getNodeXForm()->getName()<<'\n';
+ return 3;
+ }
+
+ case MatcherNode::EmitNode: {
+ const EmitNodeMatcherNode *EN = cast<EmitNodeMatcherNode>(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<PatternMarkerMatcherNode>(N)->getPattern().getSrcPattern() << '\n';
+ OS.PadToColumn(Indent*2) << "// Dst: "
+ << *cast<PatternMarkerMatcherNode>(N)->getPattern().getDstPattern() << '\n';
+ return 0;
}
assert(0 && "Unreachable");
return 0;
if (NextSize > 255) {
errs() <<
"Tblgen internal error: can't handle predicate this complex yet\n";
- exit(1);
+ // FIXME: exit(1);
}
OS.PadToColumn(Indent*2);
OS << "}\n\n";
// Emit CompletePattern matchers.
+ // FIXME: This should be const.
OS << "bool CheckComplexPattern(SDNode *Root, SDValue N,\n";
OS << " unsigned PatternNo, SmallVectorImpl<SDValue> &Result) {\n";
OS << " switch (PatternNo) {\n";
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";
}
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";
#include "Record.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include <utility>
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<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
+ std::vector<Record*>::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;
/// record into.
unsigned NextRecordedOperandNo;
- /// InputChains - This maintains the position in the recorded nodes array of
- /// all of the recorded input chains.
- SmallVector<unsigned, 2> InputChains;
+ /// MatchedChainNodes - This maintains the position in the recorded nodes
+ /// array of all of the recorded input nodes that have chains.
+ SmallVector<unsigned, 2> 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<std::pair<Record*, unsigned>, 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;
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<ResultVal> &ResultOps);
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultOfNamedOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
void EmitResultLeafAsOperand(const TreePatternNode *N,
- SmallVectorImpl<ResultVal> &ResultOps);
+ SmallVectorImpl<unsigned> &ResultOps);
void EmitResultInstructionAsOperand(const TreePatternNode *N,
- SmallVectorImpl<ResultVal> &ResultOps);
- };
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &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
/// 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<IntInit*>(N->getLeafValue()))
return AddMatcherNode(new CheckIntegerMatcherNode(II->getValue()));
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()));
// 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));
}
}
// 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<IntInit*>(N->getChild(1)->getLeafValue())) {
if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
if (N->getOperator()->getName() == "and")
// 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));
}
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
// 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()));
}
}
- // 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
// Node Result Generation
//===----------------------------------------------------------------------===//
+void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &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<ResultVal> &ResultOps){
+ SmallVectorImpl<unsigned> &ResultOps) {
assert(N->isLeaf() && "Must be a leaf");
if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
AddMatcherNode(new EmitIntegerMatcherNode(II->getValue(),N->getTypeNum(0)));
- ResultOps.push_back(ResultVal::get(NextRecordedOperandNo++));
+ ResultOps.push_back(NextRecordedOperandNo++);
return;
}
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<ResultVal> &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<unsigned> &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<ResultVal, 8> Ops;
+ SmallVector<unsigned, 8> InstOps;
for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.OperandList.size();
InstOpNo != e; ++InstOpNo) {
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<MVT::SimpleValueType, 4> 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));
+ }
+
- return;
+ // 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<unsigned> &ResultOps) {
+ assert(N->getOperator()->isSubClassOf("SDNodeXForm") && "Not SDNodeXForm?");
+
+ // Emit the operand.
+ SmallVector<unsigned, 8> InputOps;
+
+ // 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<ResultVal> &ResultOps) {
+ SmallVectorImpl<unsigned> &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);
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<ResultVal, 8> Ops;
+ SmallVector<unsigned, 8> 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));
}
// 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 <index>" command. This allows result generation stuff to be
+ // shared and factored?
+
// If the match succeeds, then we generate Pattern.
Gen.EmitResultCode();