Rework our internal representation of node predicates to expose more

structure and fix some fixmes.  We now have a TreePredicateFn class
that handles all of the decoding of these things.  This is an internal
cleanup that has no impact on the code generated by tblgen.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129670 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2011-04-17 21:38:24 +00:00
parent 461cd70311
commit 543790673c
7 changed files with 153 additions and 62 deletions

View File

@ -490,6 +490,18 @@ class SDNodeXForm<SDNode opc, code xformFunction> {
def NOOP_SDNodeXForm : SDNodeXForm<imm, [{}]>;
//===----------------------------------------------------------------------===//
// PatPred Subclasses.
//
// These allow specifying different sorts of predicates that control whether a
// node is matched.
//
class PatPred;
class CodePatPred<code predicate> : PatPred {
code PredicateCode = predicate;
}
//===----------------------------------------------------------------------===//
// Selection DAG Pattern Fragments.
@ -507,7 +519,7 @@ class PatFrag<dag ops, dag frag, code pred = [{}],
SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator {
dag Operands = ops;
dag Fragment = frag;
code Predicate = pred;
code PredicateCode = pred;
SDNodeXForm OperandTransform = xform;
}

View File

@ -459,7 +459,7 @@ def CallImmAddr : Predicate<"Subtarget->IsLegalToCallImmediateAddr(TM)">;
include "X86InstrFormats.td"
//===----------------------------------------------------------------------===//
// Pattern fragments...
// Pattern fragments.
//
// X86 specific condition code. These correspond to CondCode in

View File

@ -580,34 +580,29 @@ typedef std::map<std::string, int> DepVarMap;
/// Const iterator shorthand for DepVarMap
typedef DepVarMap::const_iterator DepVarMap_citer;
namespace {
void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) {
static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) {
if (N->isLeaf()) {
if (dynamic_cast<DefInit*>(N->getLeafValue()) != NULL) {
if (dynamic_cast<DefInit*>(N->getLeafValue()) != NULL)
DepMap[N->getName()]++;
}
} else {
for (size_t i = 0, e = N->getNumChildren(); i != e; ++i)
FindDepVarsOf(N->getChild(i), DepMap);
}
}
//! Find dependent variables within child patterns
/*!
*/
void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) {
/// Find dependent variables within child patterns
static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) {
DepVarMap depcounts;
FindDepVarsOf(N, depcounts);
for (DepVarMap_citer i = depcounts.begin(); i != depcounts.end(); ++i) {
if (i->second > 1) { // std::pair<std::string, int>
if (i->second > 1) // std::pair<std::string, int>
DepVars.insert(i->first);
}
}
}
//! Dump the dependent variable set:
#ifndef NDEBUG
void DumpDepVars(MultipleUseVarSet &DepVars) {
/// Dump the dependent variable set:
static void DumpDepVars(MultipleUseVarSet &DepVars) {
if (DepVars.empty()) {
DEBUG(errs() << "<empty set>");
} else {
@ -621,6 +616,46 @@ void DumpDepVars(MultipleUseVarSet &DepVars) {
}
#endif
//===----------------------------------------------------------------------===//
// TreePredicateFn Implementation
//===----------------------------------------------------------------------===//
std::string TreePredicateFn::getPredCode() const {
return PatFragRec->getRecord()->getValueAsCode("PredicateCode");
}
/// isAlwaysTrue - Return true if this is a noop predicate.
bool TreePredicateFn::isAlwaysTrue() const {
return getPredCode().empty();
}
/// Return the name to use in the generated code to reference this, this is
/// "Predicate_foo" if from a pattern fragment "foo".
std::string TreePredicateFn::getFnName() const {
return "Predicate_" + PatFragRec->getRecord()->getName();
}
/// getCodeToRunOnSDNode - Return the code for the function body that
/// evaluates this predicate. The argument is expected to be in "Node",
/// not N. This handles casting and conversion to a concrete node type as
/// appropriate.
std::string TreePredicateFn::getCodeToRunOnSDNode() const {
std::string ClassName;
if (PatFragRec->getOnlyTree()->isLeaf())
ClassName = "SDNode";
else {
Record *Op = PatFragRec->getOnlyTree()->getOperator();
ClassName = PatFragRec->getDAGPatterns().getSDNodeInfo(Op).getSDClassName();
}
std::string Result;
if (ClassName == "SDNode")
Result = " SDNode *N = Node;\n";
else
Result = " " + ClassName + "*N = cast<" + ClassName + ">(Node);\n";
return Result + getPredCode();
}
//===----------------------------------------------------------------------===//
@ -1015,7 +1050,7 @@ void TreePatternNode::print(raw_ostream &OS) const {
}
for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i)
OS << "<<P:" << PredicateFns[i] << ">>";
OS << "<<P:" << PredicateFns[i].getFnName() << ">>";
if (TransformFn)
OS << "<<X:" << TransformFn->getName() << ">>";
if (!getName().empty())
@ -1150,9 +1185,9 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
std::string Code = Op->getValueAsCode("Predicate");
if (!Code.empty())
FragTree->addPredicateFn("Predicate_"+Op->getName());
TreePredicateFn PredFn(Frag);
if (!PredFn.isAlwaysTrue())
FragTree->addPredicateFn(PredFn);
// Resolve formal arguments to their actual value.
if (Frag->getNumArgs()) {
@ -2063,9 +2098,9 @@ void CodeGenDAGPatterns::ParsePatternFragments() {
// If there is a code init for this fragment, keep track of the fact that
// this fragment uses it.
std::string Code = Fragments[i]->getValueAsCode("Predicate");
if (!Code.empty())
P->getOnlyTree()->addPredicateFn("Predicate_"+Fragments[i]->getName());
TreePredicateFn PredFn(P);
if (!PredFn.isAlwaysTrue())
P->getOnlyTree()->addPredicateFn(PredFn);
// If there is a node transformation corresponding to this, keep track of
// it.

View File

@ -240,6 +240,45 @@ public:
}
};
/// TreePredicateFn - This is an abstraction that represents the predicates on
/// a PatFrag node. This is a simple one-word wrapper around a pointer to
/// provide nice accessors.
class TreePredicateFn {
/// PatFragRec - This is the TreePattern for the PatFrag that we
/// originally came from.
TreePattern *PatFragRec;
public:
/// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag.
TreePredicateFn(TreePattern *N) : PatFragRec(N) {}
TreePattern *getOrigPatFragRecord() const { return PatFragRec; }
/// isAlwaysTrue - Return true if this is a noop predicate.
bool isAlwaysTrue() const;
bool operator==(const TreePredicateFn &RHS) const {
return PatFragRec == RHS.PatFragRec;
}
bool operator!=(const TreePredicateFn &RHS) const { return !(*this == RHS); }
/// Return the name to use in the generated code to reference this, this is
/// "Predicate_foo" if from a pattern fragment "foo".
std::string getFnName() const;
/// getCodeToRunOnSDNode - Return the code for the function body that
/// evaluates this predicate. The argument is expected to be in "Node",
/// not N. This handles casting and conversion to a concrete node type as
/// appropriate.
std::string getCodeToRunOnSDNode() const;
private:
std::string getPredCode() const;
};
/// FIXME: TreePatternNode's can be shared in some cases (due to dag-shaped
/// patterns), and as such should be ref counted. We currently just leak all
/// TreePatternNode objects!
@ -263,7 +302,7 @@ class TreePatternNode {
/// 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;
std::vector<TreePredicateFn> PredicateFns;
/// TransformFn - The transformation function to execute on this node before
/// it can be substituted into the resulting instruction on a pattern match.
@ -323,14 +362,18 @@ public:
return false;
}
const std::vector<std::string> &getPredicateFns() const {return PredicateFns;}
bool hasAnyPredicate() const { return !PredicateFns.empty(); }
const std::vector<TreePredicateFn> &getPredicateFns() const {
return PredicateFns;
}
void clearPredicateFns() { PredicateFns.clear(); }
void setPredicateFns(const std::vector<std::string> &Fns) {
void setPredicateFns(const std::vector<TreePredicateFn> &Fns) {
assert(PredicateFns.empty() && "Overwriting non-empty predicate list!");
PredicateFns = Fns;
}
void addPredicateFn(const std::string &Fn) {
assert(!Fn.empty() && "Empty predicate string!");
void addPredicateFn(const TreePredicateFn &Fn) {
assert(!Fn.isAlwaysTrue() && "Empty predicate string!");
if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) ==
PredicateFns.end())
PredicateFns.push_back(Fn);

View File

@ -83,6 +83,15 @@ ScopeMatcher::~ScopeMatcher() {
}
CheckPredicateMatcher::CheckPredicateMatcher(const TreePredicateFn &pred)
: Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()) {}
TreePredicateFn CheckPredicateMatcher::getPredicate() const {
return TreePredicateFn(Pred);
}
// printImpl methods.
void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
@ -129,7 +138,7 @@ printImpl(raw_ostream &OS, unsigned indent) const {
}
void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "CheckPredicate " << PredName << '\n';
OS.indent(indent) << "CheckPredicate " << getPredicate().getFnName() << '\n';
}
void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
@ -263,7 +272,7 @@ unsigned CheckPatternPredicateMatcher::getHashImpl() const {
}
unsigned CheckPredicateMatcher::getHashImpl() const {
return HashString(PredName);
return HashString(getPredicate().getFnName());
}
unsigned CheckOpcodeMatcher::getHashImpl() const {
@ -301,7 +310,6 @@ bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const {
Opcode.getEnumName();
}
bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {
const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m);
return M->OpcodeName == OpcodeName && M->VTs == VTs &&

View File

@ -25,6 +25,8 @@ namespace llvm {
class ComplexPattern;
class Record;
class SDNodeInfo;
class TreePredicateFn;
class TreePattern;
Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant,
const CodeGenDAGPatterns &CGP);
@ -419,12 +421,11 @@ private:
/// CheckPredicateMatcher - This checks the target-specific predicate to
/// see if the node is acceptable.
class CheckPredicateMatcher : public Matcher {
StringRef PredName;
TreePattern *Pred;
public:
CheckPredicateMatcher(StringRef predname)
: Matcher(CheckPredicate), PredName(predname) {}
CheckPredicateMatcher(const TreePredicateFn &pred);
StringRef getPredicateName() const { return PredName; }
TreePredicateFn getPredicate() const;
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckPredicate;
@ -436,7 +437,7 @@ public:
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
return cast<CheckPredicateMatcher>(M)->PredName == PredName;
return cast<CheckPredicateMatcher>(M)->Pred == Pred;
}
virtual unsigned getHashImpl() const;
};

View File

@ -33,8 +33,12 @@ OmitComments("omit-comments", cl::desc("Do not generate comments"),
namespace {
class MatcherTableEmitter {
const CodeGenDAGPatterns &CGP;
StringMap<unsigned> NodePredicateMap, PatternPredicateMap;
std::vector<std::string> NodePredicates, PatternPredicates;
DenseMap<TreePattern *, unsigned> NodePredicateMap;
std::vector<TreePredicateFn> NodePredicates;
StringMap<unsigned> PatternPredicateMap;
std::vector<std::string> PatternPredicates;
DenseMap<const ComplexPattern*, unsigned> ComplexPatternMap;
std::vector<const ComplexPattern*> ComplexPatterns;
@ -57,14 +61,15 @@ private:
unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
formatted_raw_ostream &OS);
unsigned getNodePredicate(StringRef PredName) {
unsigned &Entry = NodePredicateMap[PredName];
unsigned getNodePredicate(TreePredicateFn Pred) {
unsigned &Entry = NodePredicateMap[Pred.getOrigPatFragRecord()];
if (Entry == 0) {
NodePredicates.push_back(PredName.str());
NodePredicates.push_back(Pred);
Entry = NodePredicates.size();
}
return Entry-1;
}
unsigned getPatternPredicate(StringRef PredName) {
unsigned &Entry = PatternPredicateMap[PredName];
if (Entry == 0) {
@ -73,7 +78,6 @@ private:
}
return Entry-1;
}
unsigned getComplexPat(const ComplexPattern &P) {
unsigned &Entry = ComplexPatternMap[&P];
if (Entry == 0) {
@ -239,7 +243,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
return 2;
case Matcher::CheckPatternPredicate: {
StringRef Pred = cast<CheckPatternPredicateMatcher>(N)->getPredicate();
StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate();
OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ',';
if (!OmitComments)
OS.PadToColumn(CommentIndent) << "// " << Pred;
@ -247,10 +251,10 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
return 2;
}
case Matcher::CheckPredicate: {
StringRef Pred = cast<CheckPredicateMatcher>(N)->getPredicateName();
TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate();
OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ',';
if (!OmitComments)
OS.PadToColumn(CommentIndent) << "// " << Pred;
OS.PadToColumn(CommentIndent) << "// " << Pred.getFnName();
OS << '\n';
return 2;
}
@ -617,25 +621,13 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
OS << " switch (PredNo) {\n";
OS << " default: assert(0 && \"Invalid predicate in table?\");\n";
for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) {
// FIXME: Storing this by name is horrible.
TreePattern *P =PFsByName[NodePredicates[i].substr(strlen("Predicate_"))];
assert(P && "Unknown name?");
// Emit the predicate code corresponding to this pattern.
std::string Code = P->getRecord()->getValueAsCode("Predicate");
assert(!Code.empty() && "No code in this predicate");
OS << " case " << i << ": { // " << NodePredicates[i] << '\n';
std::string ClassName;
if (P->getOnlyTree()->isLeaf())
ClassName = "SDNode";
else
ClassName =
CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
if (ClassName == "SDNode")
OS << " SDNode *N = Node;\n";
else
OS << " " << ClassName << "*N = cast<" << ClassName << ">(Node);\n";
OS << Code << "\n }\n";
TreePredicateFn PredFn = NodePredicates[i];
assert(!PredFn.isAlwaysTrue() && "No code in this predicate");
OS << " case " << i << ": { // " << NodePredicates[i].getFnName() <<'\n';
OS << PredFn.getCodeToRunOnSDNode() << "\n }\n";
}
OS << " }\n";
OS << "}\n\n";