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:
parent
33e7093540
commit
1bf4053aa8
@ -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;
|
||||
|
@ -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; }
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user