1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

Add support for having multiple predicates on a TreePatternNode.

This will allow predicates to be composed, which will allow the
predicate definitions to become less redundant, and eventually
will allow DAGISelEmitter.cpp to emit less redundant code.

llvm-svn: 57562
This commit is contained in:
Dan Gohman 2008-10-15 06:17:21 +00:00
parent 33e7093540
commit 1bf4053aa8
4 changed files with 109 additions and 70 deletions

View File

@ -579,8 +579,8 @@ void TreePatternNode::print(std::ostream &OS) const {
OS << ")";
}
if (!PredicateFn.empty())
OS << "<<P:" << PredicateFn << ">>";
for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i)
OS << "<<P:" << PredicateFns[i] << ">>";
if (TransformFn)
OS << "<<X:" << TransformFn->getName() << ">>";
if (!getName().empty())
@ -602,7 +602,7 @@ bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N,
const MultipleUseVarSet &DepVars) const {
if (N == this) return true;
if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() ||
getPredicateFn() != N->getPredicateFn() ||
getPredicateFns() != N->getPredicateFns() ||
getTransformFn() != N->getTransformFn())
return false;
@ -640,7 +640,7 @@ TreePatternNode *TreePatternNode::clone() const {
}
New->setName(getName());
New->setTypes(getExtTypes());
New->setPredicateFn(getPredicateFn());
New->setPredicateFns(getPredicateFns());
New->setTransformFn(getTransformFn());
return New;
}
@ -658,9 +658,12 @@ SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) {
if (dynamic_cast<DefInit*>(Val) &&
static_cast<DefInit*>(Val)->getDef()->getName() == "node") {
// We found a use of a formal argument, replace it with its value.
Child = ArgMap[Child->getName()];
assert(Child && "Couldn't find formal argument!");
setChild(i, Child);
TreePatternNode *NewChild = ArgMap[Child->getName()];
assert(NewChild && "Couldn't find formal argument!");
assert((Child->getPredicateFns().empty() ||
NewChild->getPredicateFns() == Child->getPredicateFns()) &&
"Non-empty child predicate clobbered!");
setChild(i, NewChild);
}
} else {
getChild(i)->SubstituteFormalArguments(ArgMap);
@ -678,8 +681,16 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
if (!Op->isSubClassOf("PatFrag")) {
// Just recursively inline children nodes.
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
setChild(i, getChild(i)->InlinePatternFragments(TP));
for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
TreePatternNode *Child = getChild(i);
TreePatternNode *NewChild = Child->InlinePatternFragments(TP);
assert((Child->getPredicateFns().empty() ||
NewChild->getPredicateFns() == Child->getPredicateFns()) &&
"Non-empty child predicate clobbered!");
setChild(i, NewChild);
}
return this;
}
@ -694,6 +705,10 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
std::string Code = Op->getValueAsCode("Predicate");
if (!Code.empty())
FragTree->addPredicateFn("Predicate_"+Op->getName());
// Resolve formal arguments to their actual value.
if (Frag->getNumArgs()) {
// Compute the map of formal to actual arguments.
@ -706,7 +721,11 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
FragTree->setName(getName());
FragTree->UpdateNodeType(getExtTypes(), TP);
// Transfer in the old predicates.
for (unsigned i = 0, e = getPredicateFns().size(); i != e; ++i)
FragTree->addPredicateFn(getPredicateFns()[i]);
// Get a new copy of this fragment to stitch into here.
//delete this; // FIXME: implement refcounting!
@ -1405,7 +1424,7 @@ void CodeGenDAGPatterns::ParsePatternFragments() {
// this fragment uses it.
std::string Code = Fragments[i]->getValueAsCode("Predicate");
if (!Code.empty())
P->getOnlyTree()->setPredicateFn("Predicate_"+Fragments[i]->getName());
P->getOnlyTree()->addPredicateFn("Predicate_"+Fragments[i]->getName());
// If there is a node transformation corresponding to this, keep track of
// it.
@ -1911,7 +1930,7 @@ void CodeGenDAGPatterns::ParseInstructions() {
TreePatternNode *OpNode = InVal->clone();
// No predicate is useful on the result.
OpNode->setPredicateFn("");
OpNode->clearPredicateFns();
// Promote the xform function to be an explicit node if set.
if (Record *Xform = OpNode->getTransformFn()) {
@ -2138,7 +2157,7 @@ static void CombineChildVariants(TreePatternNode *Orig,
// Copy over properties.
R->setName(Orig->getName());
R->setPredicateFn(Orig->getPredicateFn());
R->setPredicateFns(Orig->getPredicateFns());
R->setTransformFn(Orig->getTransformFn());
R->setTypes(Orig->getExtTypes());
@ -2200,7 +2219,7 @@ static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N,
Record *Operator = N->getOperator();
// Only permit raw nodes.
if (!N->getName().empty() || !N->getPredicateFn().empty() ||
if (!N->getName().empty() || !N->getPredicateFns().empty() ||
N->getTransformFn()) {
Children.push_back(N);
return;

View File

@ -16,6 +16,8 @@
#define CODEGEN_DAGPATTERNS_H
#include <set>
#include <algorithm>
#include <vector>
#include "CodeGenTarget.h"
#include "CodeGenIntrinsics.h"
@ -158,9 +160,9 @@ class TreePatternNode {
///
std::string Name;
/// PredicateFn - The predicate function to execute on this node to check
/// for a match. If this string is empty, no predicate is involved.
std::string PredicateFn;
/// PredicateFns - The predicate functions to execute on this node to check
/// for a match. If this list is empty, no predicate is involved.
std::vector<std::string> PredicateFns;
/// TransformFn - The transformation function to execute on this node before
/// it can be substituted into the resulting instruction on a pattern match.
@ -213,8 +215,18 @@ public:
Children[i] = N;
}
const std::string &getPredicateFn() const { return PredicateFn; }
void setPredicateFn(const std::string &Fn) { PredicateFn = Fn; }
const std::vector<std::string> &getPredicateFns() const { return PredicateFns; }
void clearPredicateFns() { PredicateFns.clear(); }
void setPredicateFns(const std::vector<std::string> &Fns) {
assert(PredicateFns.empty() && "Overwriting non-empty predicate list!");
PredicateFns = Fns;
}
void addPredicateFn(const std::string &Fn) {
assert(!Fn.empty() && "Empty predicate string!");
if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) ==
PredicateFns.end())
PredicateFns.push_back(Fn);
}
Record *getTransformFn() const { return TransformFn; }
void setTransformFn(Record *Fn) { TransformFn = Fn; }

View File

@ -76,7 +76,7 @@ static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) {
// If this node has some predicate function that must match, it adds to the
// complexity of this node.
if (!P->getPredicateFn().empty())
if (!P->getPredicateFns().empty())
++Size;
// Count children in the count if they are also nodes.
@ -89,7 +89,7 @@ static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) {
Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
else if (NodeIsComplexPattern(Child))
Size += getPatternSize(Child, CGP);
else if (!Child->getPredicateFn().empty())
else if (!Child->getPredicateFns().empty())
++Size;
}
}
@ -140,8 +140,15 @@ struct PatternSortingPredicate {
PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {}
CodeGenDAGPatterns &CGP;
bool operator()(const PatternToMatch *LHS,
const PatternToMatch *RHS) {
typedef std::pair<unsigned, std::string> CodeLine;
typedef std::vector<CodeLine> CodeList;
typedef std::vector<std::pair<const PatternToMatch*, CodeList> > PatternList;
bool operator()(const std::pair<const PatternToMatch*, CodeList> &LHSPair,
const std::pair<const PatternToMatch*, CodeList> &RHSPair) {
const PatternToMatch *LHS = LHSPair.first;
const PatternToMatch *RHS = RHSPair.first;
unsigned LHSSize = getPatternSize(LHS->getSrcPattern(), CGP);
unsigned RHSSize = getPatternSize(RHS->getSrcPattern(), CGP);
LHSSize += LHS->getAddedComplexity();
@ -541,11 +548,10 @@ public:
}
}
// If there is a node predicate for this, emit the call.
if (!N->getPredicateFn().empty())
emitCheck(N->getPredicateFn() + "(" + RootName + ".getNode())");
// If there are node predicates for this, emit the calls.
for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
emitCheck(N->getPredicateFns()[i] + "(" + RootName + ".getNode())");
// If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
// a constant without a predicate fn that has more that one bit set, handle
// this as a special case. This is usually for targets that have special
@ -560,7 +566,7 @@ public:
(N->getOperator()->getName() == "and" ||
N->getOperator()->getName() == "or") &&
N->getChild(1)->isLeaf() &&
N->getChild(1)->getPredicateFn().empty()) {
N->getChild(1)->getPredicateFns().empty()) {
if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) {
if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
emitInit("SDValue " + RootName + "0" + " = " +
@ -717,9 +723,9 @@ public:
assert(0 && "Unknown leaf type!");
}
// If there is a node predicate for this, emit the call.
if (!Child->getPredicateFn().empty())
emitCheck(Child->getPredicateFn() + "(" + RootName +
// If there are node predicates for this, emit the calls.
for (unsigned i = 0, e = Child->getPredicateFns().size(); i != e; ++i)
emitCheck(Child->getPredicateFns()[i] + "(" + RootName +
".getNode())");
} else if (IntInit *II =
dynamic_cast<IntInit*>(Child->getLeafValue())) {
@ -1265,7 +1271,8 @@ public:
emitCode(After[i]);
return NodeOps;
} else if (Op->isSubClassOf("SDNodeXForm")) {
}
if (Op->isSubClassOf("SDNodeXForm")) {
assert(N->getNumChildren() == 1 && "node xform should have one child!");
// PatLeaf node - the operand may or may not be a leaf node. But it should
// behave like one.
@ -1279,11 +1286,11 @@ public:
if (isRoot)
emitCode("return Tmp" + utostr(ResNo) + ".getNode();");
return NodeOps;
} else {
N->dump();
cerr << "\n";
throw std::string("Unknown node in result pattern!");
}
N->dump();
cerr << "\n";
throw std::string("Unknown node in result pattern!");
}
/// InsertOneTypeCheck - Insert a type-check for an unresolved type in 'Pat'
@ -1641,12 +1648,6 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
std::vector<const PatternToMatch*> &PatternsOfOp = PBOI->second;
assert(!PatternsOfOp.empty() && "No patterns but map has entry?");
// We want to emit all of the matching code now. However, we want to emit
// the matches in order of minimal cost. Sort the patterns so the least
// cost one is at the start.
std::stable_sort(PatternsOfOp.begin(), PatternsOfOp.end(),
PatternSortingPredicate(CGP));
// Split them into groups by type.
std::map<MVT::SimpleValueType,
std::vector<const PatternToMatch*> > PatternsByType;
@ -1662,8 +1663,9 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
++II) {
MVT::SimpleValueType OpVT = II->first;
std::vector<const PatternToMatch*> &Patterns = II->second;
typedef std::vector<std::pair<unsigned,std::string> > CodeList;
typedef std::vector<std::pair<unsigned,std::string> >::iterator CodeListI;
typedef std::pair<unsigned, std::string> CodeLine;
typedef std::vector<CodeLine> CodeList;
typedef CodeList::iterator CodeListI;
std::vector<std::pair<const PatternToMatch*, CodeList> > CodeForPatterns;
std::vector<std::vector<std::string> > PatternOpcodes;
@ -1689,30 +1691,6 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
NumInputRootOpsCounts.push_back(NumInputRootOps);
}
// Scan the code to see if all of the patterns are reachable and if it is
// possible that the last one might not match.
bool mightNotMatch = true;
for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
CodeList &GeneratedCode = CodeForPatterns[i].second;
mightNotMatch = false;
for (unsigned j = 0, e = GeneratedCode.size(); j != e; ++j) {
if (GeneratedCode[j].first == 1) { // predicate.
mightNotMatch = true;
break;
}
}
// If this pattern definitely matches, and if it isn't the last one, the
// patterns after it CANNOT ever match. Error out.
if (mightNotMatch == false && i != CodeForPatterns.size()-1) {
cerr << "Pattern '";
CodeForPatterns[i].first->getSrcPattern()->print(*cerr.stream());
cerr << "' is impossible to select!\n";
exit(1);
}
}
// Factor target node emission code (emitted by EmitResultCode) into
// separate functions. Uniquing and share them among all instruction
// selection routines.
@ -1815,6 +1793,36 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
OS << "SDNode *Select_" << getLegalCName(OpName)
<< OpVTStr << "(const SDValue &N) {\n";
// We want to emit all of the matching code now. However, we want to emit
// the matches in order of minimal cost. Sort the patterns so the least
// cost one is at the start.
std::stable_sort(CodeForPatterns.begin(), CodeForPatterns.end(),
PatternSortingPredicate(CGP));
// Scan the code to see if all of the patterns are reachable and if it is
// possible that the last one might not match.
bool mightNotMatch = true;
for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
CodeList &GeneratedCode = CodeForPatterns[i].second;
mightNotMatch = false;
for (unsigned j = 0, e = GeneratedCode.size(); j != e; ++j) {
if (GeneratedCode[j].first == 1) { // predicate.
mightNotMatch = true;
break;
}
}
// If this pattern definitely matches, and if it isn't the last one, the
// patterns after it CANNOT ever match. Error out.
if (mightNotMatch == false && i != CodeForPatterns.size()-1) {
cerr << "Pattern '";
CodeForPatterns[i].first->getSrcPattern()->print(*cerr.stream());
cerr << "' is impossible to select!\n";
exit(1);
}
}
// Loop through and reverse all of the CodeList vectors, as we will be
// accessing them from their logical front, but accessing the end of a
// vector is more efficient.

View File

@ -71,7 +71,7 @@ struct OperandsSignature {
for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) {
TreePatternNode *Op = InstPatNode->getChild(i);
// For now, filter out any operand with a predicate.
if (!Op->getPredicateFn().empty())
if (!Op->getPredicateFns().empty())
return false;
// For now, filter out any operand with multiple values.
if (Op->getExtTypes().size() != 1)
@ -309,7 +309,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) {
continue;
// For now, filter out any instructions with predicates.
if (!InstPatNode->getPredicateFn().empty())
if (!InstPatNode->getPredicateFns().empty())
continue;
// Check all the operands.