mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
Added support for ComplexPattern. These are patterns that require C++ pattern
matching code that is not currently auto-generated by tblgen, e.g. X86 addressing mode. Selection routines for complex patterns can return multiple operands, e.g. X86 addressing mode returns 4. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24634 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
cc827e60b6
commit
0fc7198890
@ -327,16 +327,6 @@ public:
|
|||||||
SDOperand Op1, SDOperand Op2) {
|
SDOperand Op1, SDOperand Op2) {
|
||||||
return getNode(ISD::BUILTIN_OP_END+Opcode, VT, Op1, Op2);
|
return getNode(ISD::BUILTIN_OP_END+Opcode, VT, Op1, Op2);
|
||||||
}
|
}
|
||||||
SDOperand getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
|
||||||
MVT::ValueType VT2, SDOperand Op1, SDOperand Op2) {
|
|
||||||
std::vector<MVT::ValueType> ResultTys;
|
|
||||||
ResultTys.push_back(VT1);
|
|
||||||
ResultTys.push_back(VT2);
|
|
||||||
std::vector<SDOperand> Ops;
|
|
||||||
Ops.push_back(Op1);
|
|
||||||
Ops.push_back(Op2);
|
|
||||||
return getNode(ISD::BUILTIN_OP_END+Opcode, ResultTys, Ops);
|
|
||||||
}
|
|
||||||
SDOperand getTargetNode(unsigned Opcode, MVT::ValueType VT,
|
SDOperand getTargetNode(unsigned Opcode, MVT::ValueType VT,
|
||||||
SDOperand Op1, SDOperand Op2, SDOperand Op3) {
|
SDOperand Op1, SDOperand Op2, SDOperand Op3) {
|
||||||
return getNode(ISD::BUILTIN_OP_END+Opcode, VT, Op1, Op2, Op3);
|
return getNode(ISD::BUILTIN_OP_END+Opcode, VT, Op1, Op2, Op3);
|
||||||
@ -355,6 +345,55 @@ public:
|
|||||||
std::vector<SDOperand> &Ops) {
|
std::vector<SDOperand> &Ops) {
|
||||||
return getNode(ISD::BUILTIN_OP_END+Opcode, VT, Ops);
|
return getNode(ISD::BUILTIN_OP_END+Opcode, VT, Ops);
|
||||||
}
|
}
|
||||||
|
SDOperand getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||||
|
MVT::ValueType VT2, SDOperand Op1, SDOperand Op2) {
|
||||||
|
std::vector<MVT::ValueType> ResultTys;
|
||||||
|
ResultTys.push_back(VT1);
|
||||||
|
ResultTys.push_back(VT2);
|
||||||
|
std::vector<SDOperand> Ops;
|
||||||
|
Ops.push_back(Op1);
|
||||||
|
Ops.push_back(Op2);
|
||||||
|
return getNode(ISD::BUILTIN_OP_END+Opcode, ResultTys, Ops);
|
||||||
|
}
|
||||||
|
SDOperand getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||||
|
MVT::ValueType VT2, SDOperand Op1, SDOperand Op2,
|
||||||
|
SDOperand Op3) {
|
||||||
|
std::vector<MVT::ValueType> ResultTys;
|
||||||
|
ResultTys.push_back(VT1);
|
||||||
|
ResultTys.push_back(VT2);
|
||||||
|
std::vector<SDOperand> Ops;
|
||||||
|
Ops.push_back(Op1);
|
||||||
|
Ops.push_back(Op2);
|
||||||
|
Ops.push_back(Op3);
|
||||||
|
return getNode(ISD::BUILTIN_OP_END+Opcode, ResultTys, Ops);
|
||||||
|
}
|
||||||
|
SDOperand getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||||
|
MVT::ValueType VT2, SDOperand Op1, SDOperand Op2,
|
||||||
|
SDOperand Op3, SDOperand Op4) {
|
||||||
|
std::vector<MVT::ValueType> ResultTys;
|
||||||
|
ResultTys.push_back(VT1);
|
||||||
|
ResultTys.push_back(VT2);
|
||||||
|
std::vector<SDOperand> Ops;
|
||||||
|
Ops.push_back(Op1);
|
||||||
|
Ops.push_back(Op2);
|
||||||
|
Ops.push_back(Op3);
|
||||||
|
Ops.push_back(Op4);
|
||||||
|
return getNode(ISD::BUILTIN_OP_END+Opcode, ResultTys, Ops);
|
||||||
|
}
|
||||||
|
SDOperand getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||||
|
MVT::ValueType VT2, SDOperand Op1, SDOperand Op2,
|
||||||
|
SDOperand Op3, SDOperand Op4, SDOperand Op5) {
|
||||||
|
std::vector<MVT::ValueType> ResultTys;
|
||||||
|
ResultTys.push_back(VT1);
|
||||||
|
ResultTys.push_back(VT2);
|
||||||
|
std::vector<SDOperand> Ops;
|
||||||
|
Ops.push_back(Op1);
|
||||||
|
Ops.push_back(Op2);
|
||||||
|
Ops.push_back(Op3);
|
||||||
|
Ops.push_back(Op4);
|
||||||
|
Ops.push_back(Op5);
|
||||||
|
return getNode(ISD::BUILTIN_OP_END+Opcode, ResultTys, Ops);
|
||||||
|
}
|
||||||
SDOperand getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
SDOperand getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||||
MVT::ValueType VT2, std::vector<SDOperand> &Ops) {
|
MVT::ValueType VT2, std::vector<SDOperand> &Ops) {
|
||||||
std::vector<MVT::ValueType> ResultTys;
|
std::vector<MVT::ValueType> ResultTys;
|
||||||
|
@ -330,3 +330,12 @@ unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const {
|
|||||||
throw "Instruction '" + TheDef->getName() +
|
throw "Instruction '" + TheDef->getName() +
|
||||||
"' does not have an operand named '$" + Name + "'!";
|
"' does not have an operand named '$" + Name + "'!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// ComplexPattern implementation
|
||||||
|
//
|
||||||
|
ComplexPattern::ComplexPattern(Record *R) {
|
||||||
|
NumOperands = R->getValueAsInt("NumOperands");
|
||||||
|
SelectFunc = R->getValueAsString("SelectFunc");
|
||||||
|
MatchingNodes = R->getValueAsListOfDefs("MatchingNodes");
|
||||||
|
}
|
||||||
|
@ -157,6 +157,23 @@ public:
|
|||||||
bool isLittleEndianEncoding() const;
|
bool isLittleEndianEncoding() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// ComplexPattern - ComplexPattern info, corresponding to the ComplexPattern
|
||||||
|
/// tablegen class in TargetSelectionDAG.td
|
||||||
|
class ComplexPattern {
|
||||||
|
unsigned NumOperands;
|
||||||
|
std::string SelectFunc;
|
||||||
|
std::vector<Record*> MatchingNodes;
|
||||||
|
public:
|
||||||
|
ComplexPattern() : NumOperands(0) {};
|
||||||
|
ComplexPattern(Record *R);
|
||||||
|
|
||||||
|
unsigned getNumOperands() const { return NumOperands; }
|
||||||
|
const std::string &getSelectFunc() const { return SelectFunc; }
|
||||||
|
const std::vector<Record*> &getMatchingNodes() const {
|
||||||
|
return MatchingNodes;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -477,6 +477,9 @@ static unsigned char getIntrinsicType(Record *R, bool NotRegisters,
|
|||||||
} else if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
|
} else if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
|
||||||
// Using a VTSDNode or CondCodeSDNode.
|
// Using a VTSDNode or CondCodeSDNode.
|
||||||
return MVT::Other;
|
return MVT::Other;
|
||||||
|
} else if (R->isSubClassOf("ComplexPattern")) {
|
||||||
|
const CodeGenTarget &T = TP.getDAGISelEmitter().getTargetInfo();
|
||||||
|
return T.getPointerType();
|
||||||
} else if (R->getName() == "node") {
|
} else if (R->getName() == "node") {
|
||||||
// Placeholder.
|
// Placeholder.
|
||||||
return MVT::isUnknown;
|
return MVT::isUnknown;
|
||||||
@ -609,7 +612,7 @@ bool TreePatternNode::canPatternMatch(std::string &Reason, DAGISelEmitter &ISE){
|
|||||||
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
||||||
if (!getChild(i)->canPatternMatch(Reason, ISE))
|
if (!getChild(i)->canPatternMatch(Reason, ISE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If this node is a commutative operator, check that the LHS isn't an
|
// If this node is a commutative operator, check that the LHS isn't an
|
||||||
// immediate.
|
// immediate.
|
||||||
const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(getOperator());
|
const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(getOperator());
|
||||||
@ -833,6 +836,13 @@ void DAGISelEmitter::ParseNodeTransforms(std::ostream &OS) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DAGISelEmitter::ParseComplexPatterns() {
|
||||||
|
std::vector<Record*> AMs = Records.getAllDerivedDefinitions("ComplexPattern");
|
||||||
|
while (!AMs.empty()) {
|
||||||
|
ComplexPatterns.insert(std::make_pair(AMs.back(), AMs.back()));
|
||||||
|
AMs.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// ParsePatternFragments - Parse all of the PatFrag definitions in the .td
|
/// ParsePatternFragments - Parse all of the PatFrag definitions in the .td
|
||||||
@ -1204,9 +1214,10 @@ void DAGISelEmitter::ParseInstructions() {
|
|||||||
if (InVal->isLeaf() &&
|
if (InVal->isLeaf() &&
|
||||||
dynamic_cast<DefInit*>(InVal->getLeafValue())) {
|
dynamic_cast<DefInit*>(InVal->getLeafValue())) {
|
||||||
Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
|
Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
|
||||||
if (CGI.OperandList[i].Rec != InRec)
|
if (CGI.OperandList[i].Rec != InRec &&
|
||||||
|
!InRec->isSubClassOf("ComplexPattern"))
|
||||||
I->error("Operand $" + OpName +
|
I->error("Operand $" + OpName +
|
||||||
"'s register class disagrees between the operand and pattern");
|
"'s register class disagrees between the operand and pattern");
|
||||||
}
|
}
|
||||||
Operands.push_back(CGI.OperandList[i].Rec);
|
Operands.push_back(CGI.OperandList[i].Rec);
|
||||||
|
|
||||||
@ -1586,22 +1597,59 @@ void DAGISelEmitter::GenerateVariants() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NodeIsComplexPattern - return true if N is a leaf node and a subclass of
|
||||||
|
// ComplexPattern.
|
||||||
|
static bool NodeIsComplexPattern(TreePatternNode *N)
|
||||||
|
{
|
||||||
|
return (N->isLeaf() &&
|
||||||
|
dynamic_cast<DefInit*>(N->getLeafValue()) &&
|
||||||
|
static_cast<DefInit*>(N->getLeafValue())->getDef()->
|
||||||
|
isSubClassOf("ComplexPattern"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeGetComplexPattern - return the pointer to the ComplexPattern if N
|
||||||
|
// is a leaf node and a subclass of ComplexPattern, else it returns NULL.
|
||||||
|
static const ComplexPattern *NodeGetComplexPattern(TreePatternNode *N,
|
||||||
|
DAGISelEmitter &ISE)
|
||||||
|
{
|
||||||
|
if (N->isLeaf() &&
|
||||||
|
dynamic_cast<DefInit*>(N->getLeafValue()) &&
|
||||||
|
static_cast<DefInit*>(N->getLeafValue())->getDef()->
|
||||||
|
isSubClassOf("ComplexPattern")) {
|
||||||
|
return &ISE.getComplexPattern(static_cast<DefInit*>(N->getLeafValue())
|
||||||
|
->getDef());
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/// getPatternSize - Return the 'size' of this pattern. We want to match large
|
/// getPatternSize - Return the 'size' of this pattern. We want to match large
|
||||||
/// patterns before small ones. This is used to determine the size of a
|
/// patterns before small ones. This is used to determine the size of a
|
||||||
/// pattern.
|
/// pattern.
|
||||||
static unsigned getPatternSize(TreePatternNode *P) {
|
static unsigned getPatternSize(TreePatternNode *P, DAGISelEmitter &ISE) {
|
||||||
assert(isExtIntegerVT(P->getExtType()) ||
|
assert(isExtIntegerVT(P->getExtType()) ||
|
||||||
isExtFloatingPointVT(P->getExtType()) ||
|
isExtFloatingPointVT(P->getExtType()) ||
|
||||||
P->getExtType() == MVT::isVoid && "Not a valid pattern node to size!");
|
P->getExtType() == MVT::isVoid && "Not a valid pattern node to size!");
|
||||||
unsigned Size = 1; // The node itself.
|
unsigned Size = 1; // The node itself.
|
||||||
|
|
||||||
|
// FIXME: This is a hack to statically increase the priority of patterns
|
||||||
|
// which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD.
|
||||||
|
// Later we can allow complexity / cost for each pattern to be (optionally)
|
||||||
|
// specified. To get best possible pattern match we'll need to dynamically
|
||||||
|
// calculate the complexity of all patterns a dag can potentially map to.
|
||||||
|
const ComplexPattern *AM = NodeGetComplexPattern(P, ISE);
|
||||||
|
if (AM)
|
||||||
|
Size += AM->getNumOperands();
|
||||||
|
|
||||||
// Count children in the count if they are also nodes.
|
// Count children in the count if they are also nodes.
|
||||||
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) {
|
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) {
|
||||||
TreePatternNode *Child = P->getChild(i);
|
TreePatternNode *Child = P->getChild(i);
|
||||||
if (!Child->isLeaf() && Child->getExtType() != MVT::Other)
|
if (!Child->isLeaf() && Child->getExtType() != MVT::Other)
|
||||||
Size += getPatternSize(Child);
|
Size += getPatternSize(Child, ISE);
|
||||||
else if (Child->isLeaf() && dynamic_cast<IntInit*>(Child->getLeafValue())) {
|
else if (Child->isLeaf()) {
|
||||||
++Size; // Matches a ConstantSDNode.
|
if (dynamic_cast<IntInit*>(Child->getLeafValue()))
|
||||||
|
++Size; // Matches a ConstantSDNode.
|
||||||
|
else if (NodeIsComplexPattern(Child))
|
||||||
|
Size += getPatternSize(Child, ISE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1624,10 +1672,13 @@ static unsigned getResultPatternCost(TreePatternNode *P) {
|
|||||||
// In particular, we want to match maximal patterns first and lowest cost within
|
// In particular, we want to match maximal patterns first and lowest cost within
|
||||||
// a particular complexity first.
|
// a particular complexity first.
|
||||||
struct PatternSortingPredicate {
|
struct PatternSortingPredicate {
|
||||||
|
PatternSortingPredicate(DAGISelEmitter &ise) : ISE(ise) {};
|
||||||
|
DAGISelEmitter &ISE;
|
||||||
|
|
||||||
bool operator()(DAGISelEmitter::PatternToMatch *LHS,
|
bool operator()(DAGISelEmitter::PatternToMatch *LHS,
|
||||||
DAGISelEmitter::PatternToMatch *RHS) {
|
DAGISelEmitter::PatternToMatch *RHS) {
|
||||||
unsigned LHSSize = getPatternSize(LHS->first);
|
unsigned LHSSize = getPatternSize(LHS->first, ISE);
|
||||||
unsigned RHSSize = getPatternSize(RHS->first);
|
unsigned RHSSize = getPatternSize(RHS->first, ISE);
|
||||||
if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
|
if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
|
||||||
if (LHSSize < RHSSize) return false;
|
if (LHSSize < RHSSize) return false;
|
||||||
|
|
||||||
@ -1649,9 +1700,10 @@ void DAGISelEmitter::EmitMatchForPattern(TreePatternNode *N,
|
|||||||
<< ")->getSignExtended() != " << II->getValue() << ")\n"
|
<< ")->getSignExtended() != " << II->getValue() << ")\n"
|
||||||
<< " goto P" << PatternNo << "Fail;\n";
|
<< " goto P" << PatternNo << "Fail;\n";
|
||||||
return;
|
return;
|
||||||
|
} else if (!NodeIsComplexPattern(N)) {
|
||||||
|
assert(0 && "Cannot match this as a leaf value!");
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
assert(0 && "Cannot match this as a leaf value!");
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this node has a name associated with it, capture it in VarMap. If
|
// If this node has a name associated with it, capture it in VarMap. If
|
||||||
@ -1710,6 +1762,8 @@ void DAGISelEmitter::EmitMatchForPattern(TreePatternNode *N,
|
|||||||
if (LeafRec->isSubClassOf("RegisterClass") ||
|
if (LeafRec->isSubClassOf("RegisterClass") ||
|
||||||
LeafRec->isSubClassOf("Register")) {
|
LeafRec->isSubClassOf("Register")) {
|
||||||
// Handle register references. Nothing to do here.
|
// Handle register references. Nothing to do here.
|
||||||
|
} else if (LeafRec->isSubClassOf("ComplexPattern")) {
|
||||||
|
// Handle complex pattern. Nothing to do here.
|
||||||
} else if (LeafRec->isSubClassOf("ValueType")) {
|
} else if (LeafRec->isSubClassOf("ValueType")) {
|
||||||
// Make sure this is the specified value type.
|
// Make sure this is the specified value type.
|
||||||
OS << " if (cast<VTSDNode>(" << RootName << OpNo << ")->getVT() != "
|
OS << " if (cast<VTSDNode>(" << RootName << OpNo << ")->getVT() != "
|
||||||
@ -1819,9 +1873,10 @@ void DAGISelEmitter::EmitCopyToRegsForPattern(TreePatternNode *N,
|
|||||||
|
|
||||||
/// CodeGenPatternResult - Emit the action for a pattern. Now that it has
|
/// CodeGenPatternResult - Emit the action for a pattern. Now that it has
|
||||||
/// matched, we actually have to build a DAG!
|
/// matched, we actually have to build a DAG!
|
||||||
unsigned DAGISelEmitter::
|
std::pair<unsigned, unsigned> DAGISelEmitter::
|
||||||
CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
||||||
std::map<std::string,std::string> &VariableMap,
|
std::map<std::string,std::string> &VariableMap,
|
||||||
|
unsigned PatternNo,
|
||||||
std::ostream &OS, bool &HasChain, bool InFlag,
|
std::ostream &OS, bool &HasChain, bool InFlag,
|
||||||
bool isRoot) {
|
bool isRoot) {
|
||||||
// This is something selected from the pattern we matched.
|
// This is something selected from the pattern we matched.
|
||||||
@ -1832,10 +1887,12 @@ CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
|||||||
"Variable referenced but not defined and not caught earlier!");
|
"Variable referenced but not defined and not caught earlier!");
|
||||||
if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') {
|
if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') {
|
||||||
// Already selected this operand, just return the tmpval.
|
// Already selected this operand, just return the tmpval.
|
||||||
return atoi(Val.c_str()+3);
|
return std::make_pair(1, atoi(Val.c_str()+3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ComplexPattern *CP;
|
||||||
unsigned ResNo = Ctr++;
|
unsigned ResNo = Ctr++;
|
||||||
|
unsigned NumRes = 1;
|
||||||
if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
|
if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
|
||||||
switch (N->getType()) {
|
switch (N->getType()) {
|
||||||
default: assert(0 && "Unknown type for constant node!");
|
default: assert(0 && "Unknown type for constant node!");
|
||||||
@ -1850,13 +1907,27 @@ CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
|||||||
<< ResNo << "C, MVT::" << getEnumName(N->getType()) << ");\n";
|
<< ResNo << "C, MVT::" << getEnumName(N->getType()) << ");\n";
|
||||||
} else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") {
|
} else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") {
|
||||||
OS << " SDOperand Tmp" << ResNo << " = " << Val << ";\n";
|
OS << " SDOperand Tmp" << ResNo << " = " << Val << ";\n";
|
||||||
|
} else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, *this))) {
|
||||||
|
std::string Fn = CP->getSelectFunc();
|
||||||
|
NumRes = CP->getNumOperands();
|
||||||
|
OS << " SDOperand ";
|
||||||
|
for (unsigned i = 0; i < NumRes; i++) {
|
||||||
|
if (i != 0) OS << ", ";
|
||||||
|
OS << "Tmp" << i + ResNo;
|
||||||
|
}
|
||||||
|
OS << ";\n";
|
||||||
|
OS << " if (!" << Fn << "(" << Val;
|
||||||
|
for (unsigned i = 0; i < NumRes; i++)
|
||||||
|
OS << " , Tmp" << i + ResNo;
|
||||||
|
OS << ")) goto P" << PatternNo << "Fail;\n";
|
||||||
|
Ctr = ResNo + NumRes;
|
||||||
} else {
|
} else {
|
||||||
OS << " SDOperand Tmp" << ResNo << " = Select(" << Val << ");\n";
|
OS << " SDOperand Tmp" << ResNo << " = Select(" << Val << ");\n";
|
||||||
}
|
}
|
||||||
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
|
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
|
||||||
// value if used multiple times by this pattern result.
|
// value if used multiple times by this pattern result.
|
||||||
Val = "Tmp"+utostr(ResNo);
|
Val = "Tmp"+utostr(ResNo);
|
||||||
return ResNo;
|
return std::make_pair(NumRes, ResNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (N->isLeaf()) {
|
if (N->isLeaf()) {
|
||||||
@ -1868,7 +1939,7 @@ CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
|||||||
<< getQualifiedName(DI->getDef()) << ", MVT::"
|
<< getQualifiedName(DI->getDef()) << ", MVT::"
|
||||||
<< getEnumName(N->getType())
|
<< getEnumName(N->getType())
|
||||||
<< ");\n";
|
<< ");\n";
|
||||||
return ResNo;
|
return std::make_pair(1, ResNo);
|
||||||
}
|
}
|
||||||
} else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
|
} else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
|
||||||
unsigned ResNo = Ctr++;
|
unsigned ResNo = Ctr++;
|
||||||
@ -1876,21 +1947,26 @@ CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
|||||||
<< II->getValue() << ", MVT::"
|
<< II->getValue() << ", MVT::"
|
||||||
<< getEnumName(N->getType())
|
<< getEnumName(N->getType())
|
||||||
<< ");\n";
|
<< ");\n";
|
||||||
return ResNo;
|
return std::make_pair(1, ResNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
N->dump();
|
N->dump();
|
||||||
assert(0 && "Unknown leaf type!");
|
assert(0 && "Unknown leaf type!");
|
||||||
return ~0U;
|
return std::make_pair(1, ~0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
Record *Op = N->getOperator();
|
Record *Op = N->getOperator();
|
||||||
if (Op->isSubClassOf("Instruction")) {
|
if (Op->isSubClassOf("Instruction")) {
|
||||||
// Emit all of the operands.
|
// Emit all of the operands.
|
||||||
std::vector<unsigned> Ops;
|
std::vector<unsigned> Ops;
|
||||||
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
|
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
|
||||||
Ops.push_back(CodeGenPatternResult(N->getChild(i), Ctr,
|
TreePatternNode *Child = N->getChild(i);
|
||||||
VariableMap, OS, HasChain, InFlag));
|
std::pair<unsigned, unsigned> NOPair =
|
||||||
|
CodeGenPatternResult(Child, Ctr,
|
||||||
|
VariableMap, PatternNo, OS, HasChain, InFlag);
|
||||||
|
for (unsigned j = 0; j < NOPair.first; j++)
|
||||||
|
Ops.push_back(NOPair.second + j);
|
||||||
|
}
|
||||||
|
|
||||||
CodeGenInstruction &II = Target.getInstruction(Op->getName());
|
CodeGenInstruction &II = Target.getInstruction(Op->getName());
|
||||||
bool HasCtrlDep = II.hasCtrlDep;
|
bool HasCtrlDep = II.hasCtrlDep;
|
||||||
@ -1934,12 +2010,12 @@ CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
|||||||
OS << " CodeGenMap[N.getValue(0)] = Result;\n";
|
OS << " CodeGenMap[N.getValue(0)] = Result;\n";
|
||||||
OS << " CodeGenMap[N.getValue(" << NumResults
|
OS << " CodeGenMap[N.getValue(" << NumResults
|
||||||
<< ")] = Result.getValue(" << NumResults << ");\n";
|
<< ")] = Result.getValue(" << NumResults << ");\n";
|
||||||
OS << " Chain = CodeGenMap[N].getValue(" << NumResults << ");\n";
|
OS << " Chain = Result.getValue(" << NumResults << ");\n";
|
||||||
}
|
}
|
||||||
if (NumResults == 0)
|
if (NumResults == 0)
|
||||||
OS << " return Chain;\n";
|
OS << " return Chain;\n";
|
||||||
else
|
else
|
||||||
OS << " return (N.ResNo) ? Chain : CodeGenMap[N];\n";
|
OS << " return (N.ResNo) ? Chain : Result.getValue(0);\n";
|
||||||
} else {
|
} else {
|
||||||
// If this instruction is the root, and if there is only one use of it,
|
// If this instruction is the root, and if there is only one use of it,
|
||||||
// use SelectNodeTo instead of getTargetNode to avoid an allocation.
|
// use SelectNodeTo instead of getTargetNode to avoid an allocation.
|
||||||
@ -1963,11 +2039,12 @@ CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
|||||||
OS << ");\n";
|
OS << ");\n";
|
||||||
OS << " }\n";
|
OS << " }\n";
|
||||||
}
|
}
|
||||||
return ResNo;
|
return std::make_pair(1, ResNo);
|
||||||
} else if (Op->isSubClassOf("SDNodeXForm")) {
|
} else if (Op->isSubClassOf("SDNodeXForm")) {
|
||||||
assert(N->getNumChildren() == 1 && "node xform should have one child!");
|
assert(N->getNumChildren() == 1 && "node xform should have one child!");
|
||||||
unsigned OpVal = CodeGenPatternResult(N->getChild(0), Ctr,
|
unsigned OpVal = CodeGenPatternResult(N->getChild(0), Ctr,
|
||||||
VariableMap, OS, HasChain, InFlag);
|
VariableMap, PatternNo, OS, HasChain, InFlag)
|
||||||
|
.second;
|
||||||
|
|
||||||
unsigned ResNo = Ctr++;
|
unsigned ResNo = Ctr++;
|
||||||
OS << " SDOperand Tmp" << ResNo << " = Transform_" << Op->getName()
|
OS << " SDOperand Tmp" << ResNo << " = Transform_" << Op->getName()
|
||||||
@ -1976,11 +2053,11 @@ CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
|||||||
OS << " CodeGenMap[N] = Tmp" << ResNo << ";\n";
|
OS << " CodeGenMap[N] = Tmp" << ResNo << ";\n";
|
||||||
OS << " return Tmp" << ResNo << ";\n";
|
OS << " return Tmp" << ResNo << ";\n";
|
||||||
}
|
}
|
||||||
return ResNo;
|
return std::make_pair(1, ResNo);
|
||||||
} else {
|
} else {
|
||||||
N->dump();
|
N->dump();
|
||||||
assert(0 && "Unknown node in result pattern!");
|
assert(0 && "Unknown node in result pattern!");
|
||||||
return ~0U;
|
return std::make_pair(1, ~0U);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2005,10 +2082,13 @@ static bool InsertOneTypeCheck(TreePatternNode *Pat, TreePatternNode *Other,
|
|||||||
if (!Pat->hasTypeSet()) {
|
if (!Pat->hasTypeSet()) {
|
||||||
// Move a type over from 'other' to 'pat'.
|
// Move a type over from 'other' to 'pat'.
|
||||||
Pat->setType(Other->getType());
|
Pat->setType(Other->getType());
|
||||||
OS << " if (" << Prefix << ".getValueType() != MVT::"
|
OS << " if (" << Prefix << ".Val->getValueType(0) != MVT::"
|
||||||
<< getName(Pat->getType()) << ") goto P" << PatternNo << "Fail;\n";
|
<< getName(Pat->getType()) << ") goto P" << PatternNo << "Fail;\n";
|
||||||
return true;
|
return true;
|
||||||
} else if (Pat->isLeaf()) {
|
} else if (Pat->isLeaf()) {
|
||||||
|
if (NodeIsComplexPattern(Pat))
|
||||||
|
OS << " if (" << Prefix << ".Val->getValueType(0) != MVT::"
|
||||||
|
<< getName(Pat->getType()) << ") goto P" << PatternNo << "Fail;\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2038,7 +2118,7 @@ void DAGISelEmitter::EmitCodeForPattern(PatternToMatch &Pattern,
|
|||||||
OS << "\n // Emits: ";
|
OS << "\n // Emits: ";
|
||||||
Pattern.second->print(OS);
|
Pattern.second->print(OS);
|
||||||
OS << "\n";
|
OS << "\n";
|
||||||
OS << " // Pattern complexity = " << getPatternSize(Pattern.first)
|
OS << " // Pattern complexity = " << getPatternSize(Pattern.first, *this)
|
||||||
<< " cost = " << getResultPatternCost(Pattern.second) << "\n";
|
<< " cost = " << getResultPatternCost(Pattern.second) << "\n";
|
||||||
|
|
||||||
// Emit the matcher, capturing named arguments in VariableMap.
|
// Emit the matcher, capturing named arguments in VariableMap.
|
||||||
@ -2088,7 +2168,7 @@ void DAGISelEmitter::EmitCodeForPattern(PatternToMatch &Pattern,
|
|||||||
|
|
||||||
unsigned TmpNo = 0;
|
unsigned TmpNo = 0;
|
||||||
CodeGenPatternResult(Pattern.second,
|
CodeGenPatternResult(Pattern.second,
|
||||||
TmpNo, VariableMap, OS, HasChain, InFlag, true /*the root*/);
|
TmpNo, VariableMap, PatternNo, OS, HasChain, InFlag, true /*the root*/);
|
||||||
delete Pat;
|
delete Pat;
|
||||||
|
|
||||||
OS << " }\n P" << PatternNo << "Fail:\n";
|
OS << " }\n P" << PatternNo << "Fail:\n";
|
||||||
@ -2166,23 +2246,31 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
|
|||||||
// Group the patterns by their top-level opcodes.
|
// Group the patterns by their top-level opcodes.
|
||||||
std::map<Record*, std::vector<PatternToMatch*>,
|
std::map<Record*, std::vector<PatternToMatch*>,
|
||||||
CompareByRecordName> PatternsByOpcode;
|
CompareByRecordName> PatternsByOpcode;
|
||||||
for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i)
|
for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
|
||||||
if (!PatternsToMatch[i].first->isLeaf()) {
|
TreePatternNode *Node = PatternsToMatch[i].first;
|
||||||
PatternsByOpcode[PatternsToMatch[i].first->getOperator()]
|
if (!Node->isLeaf()) {
|
||||||
.push_back(&PatternsToMatch[i]);
|
PatternsByOpcode[Node->getOperator()].push_back(&PatternsToMatch[i]);
|
||||||
} else {
|
} else {
|
||||||
|
const ComplexPattern *CP;
|
||||||
if (IntInit *II =
|
if (IntInit *II =
|
||||||
dynamic_cast<IntInit*>(PatternsToMatch[i].first->getLeafValue())) {
|
dynamic_cast<IntInit*>(Node->getLeafValue())) {
|
||||||
PatternsByOpcode[getSDNodeNamed("imm")].push_back(&PatternsToMatch[i]);
|
PatternsByOpcode[getSDNodeNamed("imm")].push_back(&PatternsToMatch[i]);
|
||||||
|
} else if ((CP = NodeGetComplexPattern(Node, *this))) {
|
||||||
|
std::vector<Record*> OpNodes = CP->getMatchingNodes();
|
||||||
|
for (unsigned j = 0, e = OpNodes.size(); j != e; j++) {
|
||||||
|
PatternsByOpcode[OpNodes[j]].insert(PatternsByOpcode[OpNodes[j]].begin(),
|
||||||
|
&PatternsToMatch[i]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Unrecognized opcode '";
|
std::cerr << "Unrecognized opcode '";
|
||||||
PatternsToMatch[i].first->dump();
|
Node->dump();
|
||||||
std::cerr << "' on tree pattern '";
|
std::cerr << "' on tree pattern '";
|
||||||
std::cerr << PatternsToMatch[i].second->getOperator()->getName();
|
std::cerr << PatternsToMatch[i].second->getOperator()->getName();
|
||||||
std::cerr << "'!\n";
|
std::cerr << "'!\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Loop over all of the case statements.
|
// Loop over all of the case statements.
|
||||||
for (std::map<Record*, std::vector<PatternToMatch*>,
|
for (std::map<Record*, std::vector<PatternToMatch*>,
|
||||||
@ -2197,7 +2285,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
|
|||||||
// the matches in order of minimal cost. Sort the patterns so the least
|
// the matches in order of minimal cost. Sort the patterns so the least
|
||||||
// cost one is at the start.
|
// cost one is at the start.
|
||||||
std::stable_sort(Patterns.begin(), Patterns.end(),
|
std::stable_sort(Patterns.begin(), Patterns.end(),
|
||||||
PatternSortingPredicate());
|
PatternSortingPredicate(*this));
|
||||||
|
|
||||||
for (unsigned i = 0, e = Patterns.size(); i != e; ++i)
|
for (unsigned i = 0, e = Patterns.size(); i != e; ++i)
|
||||||
EmitCodeForPattern(*Patterns[i], OS);
|
EmitCodeForPattern(*Patterns[i], OS);
|
||||||
@ -2227,6 +2315,7 @@ void DAGISelEmitter::run(std::ostream &OS) {
|
|||||||
|
|
||||||
ParseNodeInfo();
|
ParseNodeInfo();
|
||||||
ParseNodeTransforms(OS);
|
ParseNodeTransforms(OS);
|
||||||
|
ParseComplexPatterns();
|
||||||
ParsePatternFragments(OS);
|
ParsePatternFragments(OS);
|
||||||
ParseInstructions();
|
ParseInstructions();
|
||||||
ParsePatterns();
|
ParsePatterns();
|
||||||
|
@ -26,6 +26,7 @@ namespace llvm {
|
|||||||
class TreePattern;
|
class TreePattern;
|
||||||
class TreePatternNode;
|
class TreePatternNode;
|
||||||
class DAGISelEmitter;
|
class DAGISelEmitter;
|
||||||
|
class ComplexPattern;
|
||||||
|
|
||||||
/// MVT::DAGISelGenValueType - These are some extended forms of MVT::ValueType
|
/// MVT::DAGISelGenValueType - These are some extended forms of MVT::ValueType
|
||||||
/// that we use as lattice values during type inferrence.
|
/// that we use as lattice values during type inferrence.
|
||||||
@ -365,6 +366,7 @@ private:
|
|||||||
|
|
||||||
std::map<Record*, SDNodeInfo> SDNodes;
|
std::map<Record*, SDNodeInfo> SDNodes;
|
||||||
std::map<Record*, std::pair<Record*, std::string> > SDNodeXForms;
|
std::map<Record*, std::pair<Record*, std::string> > SDNodeXForms;
|
||||||
|
std::map<Record*, ComplexPattern> ComplexPatterns;
|
||||||
std::map<Record*, TreePattern*> PatternFragments;
|
std::map<Record*, TreePattern*> PatternFragments;
|
||||||
std::map<Record*, DAGInstruction> Instructions;
|
std::map<Record*, DAGInstruction> Instructions;
|
||||||
|
|
||||||
@ -387,15 +389,20 @@ public:
|
|||||||
return SDNodes.find(R)->second;
|
return SDNodes.find(R)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
TreePattern *getPatternFragment(Record *R) const {
|
|
||||||
assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
|
|
||||||
return PatternFragments.find(R)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::pair<Record*, std::string> &getSDNodeTransform(Record *R) const {
|
const std::pair<Record*, std::string> &getSDNodeTransform(Record *R) const {
|
||||||
assert(SDNodeXForms.count(R) && "Invalid transform!");
|
assert(SDNodeXForms.count(R) && "Invalid transform!");
|
||||||
return SDNodeXForms.find(R)->second;
|
return SDNodeXForms.find(R)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ComplexPattern &getComplexPattern(Record *R) const {
|
||||||
|
assert(ComplexPatterns.count(R) && "Unknown addressing mode!");
|
||||||
|
return ComplexPatterns.find(R)->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreePattern *getPatternFragment(Record *R) const {
|
||||||
|
assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
|
||||||
|
return PatternFragments.find(R)->second;
|
||||||
|
}
|
||||||
|
|
||||||
const DAGInstruction &getInstruction(Record *R) const {
|
const DAGInstruction &getInstruction(Record *R) const {
|
||||||
assert(Instructions.count(R) && "Unknown instruction!");
|
assert(Instructions.count(R) && "Unknown instruction!");
|
||||||
@ -405,6 +412,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void ParseNodeInfo();
|
void ParseNodeInfo();
|
||||||
void ParseNodeTransforms(std::ostream &OS);
|
void ParseNodeTransforms(std::ostream &OS);
|
||||||
|
void ParseComplexPatterns();
|
||||||
void ParsePatternFragments(std::ostream &OS);
|
void ParsePatternFragments(std::ostream &OS);
|
||||||
void ParseInstructions();
|
void ParseInstructions();
|
||||||
void ParsePatterns();
|
void ParsePatterns();
|
||||||
@ -420,10 +428,11 @@ private:
|
|||||||
std::ostream &OS, bool &HasChain);
|
std::ostream &OS, bool &HasChain);
|
||||||
void EmitCopyToRegsForPattern(TreePatternNode *N, const std::string &RootName,
|
void EmitCopyToRegsForPattern(TreePatternNode *N, const std::string &RootName,
|
||||||
std::ostream &OS, bool &HasChain, bool &InFlag);
|
std::ostream &OS, bool &HasChain, bool &InFlag);
|
||||||
unsigned CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
std::pair<unsigned, unsigned>
|
||||||
std::map<std::string,std::string> &VariableMap,
|
CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr,
|
||||||
std::ostream &OS, bool &HasChain, bool InFlag,
|
std::map<std::string,std::string> &VariableMap,
|
||||||
bool isRoot = false);
|
unsigned PatternNo, std::ostream &OS, bool &HasChain,
|
||||||
|
bool InFlag, bool isRoot = false);
|
||||||
void EmitCodeForPattern(PatternToMatch &Pattern, std::ostream &OS);
|
void EmitCodeForPattern(PatternToMatch &Pattern, std::ostream &OS);
|
||||||
void EmitInstructionSelector(std::ostream &OS);
|
void EmitInstructionSelector(std::ostream &OS);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user