Lots of improvements to the new dagisel emitter. This gets it to

the point where it is to the 95% feature complete mark, it just
needs result updating to be done (then testing, optimization 
etc).

More specificallly, this adds support for chain and flag handling
on the result nodes, support for sdnodexforms, support for variadic
nodes, memrefs, pinned physreg inputs, and probably lots of other
stuff.

In the old DAGISelEmitter, this deletes the dead code related to
OperatorMap, cleans up a variety of dead stuff handling "implicit
remapping" from things like globaladdr -> targetglobaladdr (which
is no longer used because globaladdr always needs to be legalized),
and some minor formatting fixes.




git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@96716 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-02-21 03:22:59 +00:00
parent a170b5e818
commit 8e946bea14
6 changed files with 1024 additions and 233 deletions

View File

@ -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<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;
}
@ -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<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++];
@ -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<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
@ -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();
}
}

View File

@ -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<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
@ -296,8 +297,6 @@ private:
// 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.
@ -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<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);
@ -873,53 +857,10 @@ PatternCodeEmitter::EmitResultCode(TreePatternNode *N,
" = 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.
@ -931,9 +872,6 @@ PatternCodeEmitter::EmitResultCode(TreePatternNode *N,
}
NodeOps.push_back(getValueName(Val));
}
if (ModifiedVal)
VariableMap[VarName] = Val;
return NodeOps;
}
if (N->isLeaf()) {

View File

@ -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) << "<null next field>\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 <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);
}

View File

@ -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<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,
@ -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<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 {
const PatternToMatch &Pattern;
public:
EmitNodeMatcherNode(const PatternToMatch &pattern)
: MatcherNode(EmitNode), Pattern(pattern) {}
std::string OpcodeName;
const SmallVector<MVT::SimpleValueType, 3> VTs;
const SmallVector<unsigned, 6> 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

View File

@ -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<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) {}
@ -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<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";
@ -219,6 +238,14 @@ EmitMatcher(const MatcherNode *N, unsigned Indent) {
<< 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, "
@ -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<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;
@ -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<SDValue> &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";

View File

@ -12,29 +12,42 @@
#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;
@ -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<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;
@ -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<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
@ -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<IntInit*>(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<IntInit*>(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<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;
}
@ -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<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) {
@ -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<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));
}
// 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;
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<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);
@ -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<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));
}
@ -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 <index>" command. This allows result generation stuff to be
// shared and factored?
// If the match succeeds, then we generate Pattern.
Gen.EmitResultCode();