[llvm] r347992 - TableGen/ISel: Allow PatFrag predicate code to access captured operands
Nicolai Haehnle via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 30 06:15:13 PST 2018
Author: nha
Date: Fri Nov 30 06:15:13 2018
New Revision: 347992
URL: http://llvm.org/viewvc/llvm-project?rev=347992&view=rev
Log:
TableGen/ISel: Allow PatFrag predicate code to access captured operands
Summary:
This simplifies writing predicates for pattern fragments that are
automatically re-associated or commuted.
For example, a followup patch adds patterns for fragments of the form
(add (shl $x, $y), $z) to the AMDGPU backend. Such patterns are
automatically commuted to (add $z, (shl $x, $y)), which makes it basically
impossible to refer to $x, $y, and $z generically in the PredicateCode.
With this change, the PredicateCode can refer to $x, $y, and $z simply
as `Operands[i]`.
Test confirmed that there are no changes to any of the generated files
when building all (non-experimental) targets.
Change-Id: I61c00ace7eed42c1d4edc4c5351174b56b77a79c
Reviewers: arsenm, rampitec, RKSimon, craig.topper, hfinkel, uweigand
Subscribers: wdng, tpr, llvm-commits
Differential Revision: https://reviews.llvm.org/D51994
Modified:
llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h
llvm/trunk/include/llvm/Target/TargetSelectionDAG.td
llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp
llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h
llvm/trunk/utils/TableGen/DAGISelMatcher.cpp
llvm/trunk/utils/TableGen/DAGISelMatcher.h
llvm/trunk/utils/TableGen/DAGISelMatcherEmitter.cpp
llvm/trunk/utils/TableGen/DAGISelMatcherGen.cpp
llvm/trunk/utils/TableGen/FastISelEmitter.cpp
llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h Fri Nov 30 06:15:13 2018
@@ -132,6 +132,7 @@ public:
OPC_CheckChild2Same, OPC_CheckChild3Same,
OPC_CheckPatternPredicate,
OPC_CheckPredicate,
+ OPC_CheckPredicateWithOperands,
OPC_CheckOpcode,
OPC_SwitchOpcode,
OPC_CheckType,
@@ -267,6 +268,17 @@ public:
llvm_unreachable("Tblgen should generate the implementation of this!");
}
+ /// CheckNodePredicateWithOperands - This function is generated by tblgen in
+ /// the target.
+ /// It runs node predicate number PredNo and returns true if it succeeds or
+ /// false if it fails. The number is a private implementation detail to the
+ /// code tblgen produces.
+ virtual bool CheckNodePredicateWithOperands(
+ SDNode *N, unsigned PredNo,
+ const SmallVectorImpl<SDValue> &Operands) const {
+ llvm_unreachable("Tblgen should generate the implementation of this!");
+ }
+
virtual bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N,
unsigned PatternNo,
SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) {
Modified: llvm/trunk/include/llvm/Target/TargetSelectionDAG.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetSelectionDAG.td?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetSelectionDAG.td (original)
+++ llvm/trunk/include/llvm/Target/TargetSelectionDAG.td Fri Nov 30 06:15:13 2018
@@ -630,6 +630,15 @@ class PatFrags<dag ops, list<dag> frags,
code ImmediateCode = [{}];
SDNodeXForm OperandTransform = xform;
+ // When this is set, the PredicateCode may refer to a constant Operands
+ // vector which contains the captured nodes of the DAG, in the order listed
+ // by the Operands field above.
+ //
+ // This is useful when Fragments involves associative / commutative
+ // operators: a single piece of code can easily refer to all operands even
+ // when re-associated / commuted variants of the fragment are matched.
+ bit PredicateCodeUsesOperands = 0;
+
// Define a few pre-packaged predicates. This helps GlobalISel import
// existing rules from SelectionDAG for many common cases.
// They will be tested prior to the code in pred and must not be used in
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Fri Nov 30 06:15:13 2018
@@ -3207,6 +3207,18 @@ void SelectionDAGISel::SelectCodeCommon(
N.getNode()))
break;
continue;
+ case OPC_CheckPredicateWithOperands: {
+ unsigned OpNum = MatcherTable[MatcherIndex++];
+ SmallVector<SDValue, 8> Operands;
+
+ for (unsigned i = 0; i < OpNum; ++i)
+ Operands.push_back(RecordedNodes[MatcherTable[MatcherIndex++]].first);
+
+ unsigned PredNo = MatcherTable[MatcherIndex++];
+ if (!CheckNodePredicateWithOperands(N.getNode(), PredNo, Operands))
+ break;
+ continue;
+ }
case OPC_CheckComplexPat: {
unsigned CPNum = MatcherTable[MatcherIndex++];
unsigned RecNo = MatcherTable[MatcherIndex++];
Modified: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp Fri Nov 30 06:15:13 2018
@@ -824,6 +824,20 @@ TypeInfer::ValidateOnExit::~ValidateOnEx
}
#endif
+
+//===----------------------------------------------------------------------===//
+// ScopedName Implementation
+//===----------------------------------------------------------------------===//
+
+bool ScopedName::operator==(const ScopedName &o) const {
+ return Scope == o.Scope && Identifier == o.Identifier;
+}
+
+bool ScopedName::operator!=(const ScopedName &o) const {
+ return !(*this == o);
+}
+
+
//===----------------------------------------------------------------------===//
// TreePredicateFn Implementation
//===----------------------------------------------------------------------===//
@@ -1069,6 +1083,9 @@ bool TreePredicateFn::isPredefinedPredic
return false;
return Result == Value;
}
+bool TreePredicateFn::usesOperands() const {
+ return isPredefinedPredicateEqualTo("PredicateCodeUsesOperands", true);
+}
bool TreePredicateFn::isLoad() const {
return isPredefinedPredicateEqualTo("IsLoad", true);
}
@@ -1250,7 +1267,7 @@ std::string TreePredicateFn::getCodeToRu
else
Result = " auto *N = cast<" + ClassName.str() + ">(Node);\n";
- return Result + getPredCode();
+ return (Twine(Result) + " (void)N;\n" + getPredCode()).str();
}
//===----------------------------------------------------------------------===//
@@ -1276,7 +1293,7 @@ static unsigned getPatternSize(const Tre
// If this node has some predicate function that must match, it adds to the
// complexity of this node.
- if (!P->getPredicateFns().empty())
+ if (!P->getPredicateCalls().empty())
++Size;
// Count children in the count if they are also nodes.
@@ -1296,7 +1313,7 @@ static unsigned getPatternSize(const Tre
Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
else if (Child->getComplexPatternInfo(CGP))
Size += getPatternSize(Child, CGP);
- else if (!Child->getPredicateFns().empty())
+ else if (!Child->getPredicateCalls().empty())
++Size;
}
}
@@ -1751,13 +1768,19 @@ void TreePatternNode::print(raw_ostream
OS << ")";
}
- for (const TreePredicateFn &Pred : PredicateFns)
- OS << "<<P:" << Pred.getFnName() << ">>";
+ for (const TreePredicateCall &Pred : PredicateCalls) {
+ OS << "<<P:";
+ if (Pred.Scope)
+ OS << Pred.Scope << ":";
+ OS << Pred.Fn.getFnName() << ">>";
+ }
if (TransformFn)
OS << "<<X:" << TransformFn->getName() << ">>";
if (!getName().empty())
OS << ":$" << getName();
+ for (const ScopedName &Name : NamesAsPredicateArg)
+ OS << ":$pred:" << Name.getScope() << ":" << Name.getIdentifier();
}
void TreePatternNode::dump() const {
print(errs());
@@ -1774,7 +1797,7 @@ bool TreePatternNode::isIsomorphicTo(con
const MultipleUseVarSet &DepVars) const {
if (N == this) return true;
if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() ||
- getPredicateFns() != N->getPredicateFns() ||
+ getPredicateCalls() != N->getPredicateCalls() ||
getTransformFn() != N->getTransformFn())
return false;
@@ -1812,8 +1835,9 @@ TreePatternNodePtr TreePatternNode::clon
getNumTypes());
}
New->setName(getName());
+ New->setNamesAsPredicateArg(getNamesAsPredicateArg());
New->Types = Types;
- New->setPredicateFns(getPredicateFns());
+ New->setPredicateCalls(getPredicateCalls());
New->setTransformFn(getTransformFn());
return New;
}
@@ -1845,8 +1869,8 @@ void TreePatternNode::SubstituteFormalAr
// We found a use of a formal argument, replace it with its value.
TreePatternNodePtr NewChild = ArgMap[Child->getName()];
assert(NewChild && "Couldn't find formal argument!");
- assert((Child->getPredicateFns().empty() ||
- NewChild->getPredicateFns() == Child->getPredicateFns()) &&
+ assert((Child->getPredicateCalls().empty() ||
+ NewChild->getPredicateCalls() == Child->getPredicateCalls()) &&
"Non-empty child predicate clobbered!");
setChild(i, std::move(NewChild));
}
@@ -1892,8 +1916,8 @@ void TreePatternNode::InlinePatternFragm
return;
for (auto NewChild : ChildAlternatives[i])
- assert((Child->getPredicateFns().empty() ||
- NewChild->getPredicateFns() == Child->getPredicateFns()) &&
+ assert((Child->getPredicateCalls().empty() ||
+ NewChild->getPredicateCalls() == Child->getPredicateCalls()) &&
"Non-empty child predicate clobbered!");
}
@@ -1911,7 +1935,8 @@ void TreePatternNode::InlinePatternFragm
// Copy over properties.
R->setName(getName());
- R->setPredicateFns(getPredicateFns());
+ R->setNamesAsPredicateArg(getNamesAsPredicateArg());
+ R->setPredicateCalls(getPredicateCalls());
R->setTransformFn(getTransformFn());
for (unsigned i = 0, e = getNumTypes(); i != e; ++i)
R->setType(i, getExtType(i));
@@ -1946,10 +1971,19 @@ void TreePatternNode::InlinePatternFragm
return;
}
+ TreePredicateFn PredFn(Frag);
+ unsigned Scope = 0;
+ if (TreePredicateFn(Frag).usesOperands())
+ Scope = TP.getDAGPatterns().allocateScope();
+
// Compute the map of formal to actual arguments.
std::map<std::string, TreePatternNodePtr> ArgMap;
for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) {
- const TreePatternNodePtr &Child = getChildShared(i);
+ TreePatternNodePtr Child = getChildShared(i);
+ if (Scope != 0) {
+ Child = Child->clone();
+ Child->addNameAsPredicateArg(ScopedName(Scope, Frag->getArgName(i)));
+ }
ArgMap[Frag->getArgName(i)] = Child;
}
@@ -1957,9 +1991,8 @@ void TreePatternNode::InlinePatternFragm
for (auto Alternative : Frag->getTrees()) {
TreePatternNodePtr FragTree = Alternative->clone();
- TreePredicateFn PredFn(Frag);
if (!PredFn.isAlwaysTrue())
- FragTree->addPredicateFn(PredFn);
+ FragTree->addPredicateCall(PredFn, Scope);
// Resolve formal arguments to their actual value.
if (Frag->getNumArgs())
@@ -1972,8 +2005,8 @@ void TreePatternNode::InlinePatternFragm
FragTree->UpdateNodeType(i, getExtType(i), TP);
// Transfer in the old predicates.
- for (const TreePredicateFn &Pred : getPredicateFns())
- FragTree->addPredicateFn(Pred);
+ for (const TreePredicateCall &Pred : getPredicateCalls())
+ FragTree->addPredicateCall(Pred);
// The fragment we inlined could have recursive inlining that is needed. See
// if there are any pattern fragments in it and inline them as needed.
@@ -3596,7 +3629,7 @@ void CodeGenDAGPatterns::parseInstructio
TreePatternNodePtr OpNode = InVal->clone();
// No predicate is useful on the result.
- OpNode->clearPredicateFns();
+ OpNode->clearPredicateCalls();
// Promote the xform function to be an explicit node if set.
if (Record *Xform = OpNode->getTransformFn()) {
@@ -4251,7 +4284,8 @@ static void CombineChildVariants(
// Copy over properties.
R->setName(Orig->getName());
- R->setPredicateFns(Orig->getPredicateFns());
+ R->setNamesAsPredicateArg(Orig->getNamesAsPredicateArg());
+ R->setPredicateCalls(Orig->getPredicateCalls());
R->setTransformFn(Orig->getTransformFn());
for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i)
R->setType(i, Orig->getExtType(i));
@@ -4303,7 +4337,7 @@ GatherChildrenOfAssociativeOpcode(TreePa
Record *Operator = N->getOperator();
// Only permit raw nodes.
- if (!N->getName().empty() || !N->getPredicateFns().empty() ||
+ if (!N->getName().empty() || !N->getPredicateCalls().empty() ||
N->getTransformFn()) {
Children.push_back(N);
return;
Modified: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h (original)
+++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h Fri Nov 30 06:15:13 2018
@@ -408,6 +408,29 @@ struct SDTypeConstraint {
TreePattern &TP) const;
};
+/// ScopedName - A name of a node associated with a "scope" that indicates
+/// the context (e.g. instance of Pattern or PatFrag) in which the name was
+/// used. This enables substitution of pattern fragments while keeping track
+/// of what name(s) were originally given to various nodes in the tree.
+class ScopedName {
+ unsigned Scope;
+ std::string Identifier;
+public:
+ ScopedName(unsigned Scope, StringRef Identifier)
+ : Scope(Scope), Identifier(Identifier) {
+ assert(Scope != 0 &&
+ "Scope == 0 is used to indicate predicates without arguments");
+ }
+
+ unsigned getScope() const { return Scope; }
+ const std::string &getIdentifier() const { return Identifier; }
+
+ std::string getFullName() const;
+
+ bool operator==(const ScopedName &o) const;
+ bool operator!=(const ScopedName &o) const;
+};
+
/// SDNodeInfo - One of these records is created for each SDNode instance in
/// the target .td file. This represents the various dag nodes we will be
/// processing.
@@ -503,6 +526,9 @@ public:
/// usable as part of an identifier.
StringRef getImmTypeIdentifier() const;
+ // Predicate code uses the PatFrag's captured operands.
+ bool usesOperands() const;
+
// Is the desired predefined predicate for a load?
bool isLoad() const;
// Is the desired predefined predicate for a store?
@@ -570,6 +596,23 @@ private:
bool isPredefinedPredicateEqualTo(StringRef Field, bool Value) const;
};
+struct TreePredicateCall {
+ TreePredicateFn Fn;
+
+ // Scope -- unique identifier for retrieving named arguments. 0 is used when
+ // the predicate does not use named arguments.
+ unsigned Scope;
+
+ TreePredicateCall(const TreePredicateFn &Fn, unsigned Scope)
+ : Fn(Fn), Scope(Scope) {}
+
+ bool operator==(const TreePredicateCall &o) const {
+ return Fn == o.Fn && Scope == o.Scope;
+ }
+ bool operator!=(const TreePredicateCall &o) const {
+ return !(*this == o);
+ }
+};
class TreePatternNode {
/// The type of each node result. Before and during type inference, each
@@ -589,9 +632,11 @@ class TreePatternNode {
///
std::string Name;
- /// PredicateFns - The predicate functions to execute on this node to check
+ std::vector<ScopedName> NamesAsPredicateArg;
+
+ /// PredicateCalls - The predicate functions to execute on this node to check
/// for a match. If this list is empty, no predicate is involved.
- std::vector<TreePredicateFn> PredicateFns;
+ std::vector<TreePredicateCall> PredicateCalls;
/// TransformFn - The transformation function to execute on this node before
/// it can be substituted into the resulting instruction on a pattern match.
@@ -615,6 +660,16 @@ public:
const std::string &getName() const { return Name; }
void setName(StringRef N) { Name.assign(N.begin(), N.end()); }
+ const std::vector<ScopedName> &getNamesAsPredicateArg() const {
+ return NamesAsPredicateArg;
+ }
+ void setNamesAsPredicateArg(const std::vector<ScopedName>& Names) {
+ NamesAsPredicateArg = Names;
+ }
+ void addNameAsPredicateArg(const ScopedName &N) {
+ NamesAsPredicateArg.push_back(N);
+ }
+
bool isLeaf() const { return Val != nullptr; }
// Type accessors.
@@ -661,20 +716,24 @@ public:
bool hasPossibleType() const;
bool setDefaultMode(unsigned Mode);
- bool hasAnyPredicate() const { return !PredicateFns.empty(); }
+ bool hasAnyPredicate() const { return !PredicateCalls.empty(); }
- const std::vector<TreePredicateFn> &getPredicateFns() const {
- return PredicateFns;
+ const std::vector<TreePredicateCall> &getPredicateCalls() const {
+ return PredicateCalls;
}
- void clearPredicateFns() { PredicateFns.clear(); }
- void setPredicateFns(const std::vector<TreePredicateFn> &Fns) {
- assert(PredicateFns.empty() && "Overwriting non-empty predicate list!");
- PredicateFns = Fns;
- }
- void addPredicateFn(const TreePredicateFn &Fn) {
- assert(!Fn.isAlwaysTrue() && "Empty predicate string!");
- assert(!is_contained(PredicateFns, Fn) && "predicate applied recursively");
- PredicateFns.push_back(Fn);
+ void clearPredicateCalls() { PredicateCalls.clear(); }
+ void setPredicateCalls(const std::vector<TreePredicateCall> &Calls) {
+ assert(PredicateCalls.empty() && "Overwriting non-empty predicate list!");
+ PredicateCalls = Calls;
+ }
+ void addPredicateCall(const TreePredicateCall &Call) {
+ assert(!Call.Fn.isAlwaysTrue() && "Empty predicate string!");
+ assert(!is_contained(PredicateCalls, Call) && "predicate applied recursively");
+ PredicateCalls.push_back(Call);
+ }
+ void addPredicateCall(const TreePredicateFn &Fn, unsigned Scope) {
+ assert((Scope != 0) == Fn.usesOperands());
+ addPredicateCall(TreePredicateCall(Fn, Scope));
}
Record *getTransformFn() const { return TransformFn; }
@@ -1081,6 +1140,8 @@ class CodeGenDAGPatterns {
using PatternRewriterFn = std::function<void (TreePattern *)>;
PatternRewriterFn PatternRewriter;
+ unsigned NumScopes = 0;
+
public:
CodeGenDAGPatterns(RecordKeeper &R,
PatternRewriterFn PatternRewriter = nullptr);
@@ -1196,6 +1257,8 @@ public:
bool hasTargetIntrinsics() { return !TgtIntrinsics.empty(); }
+ unsigned allocateScope() { return ++NumScopes; }
+
private:
void ParseNodeInfo();
void ParseNodeTransforms();
Modified: llvm/trunk/utils/TableGen/DAGISelMatcher.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DAGISelMatcher.cpp?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/DAGISelMatcher.cpp (original)
+++ llvm/trunk/utils/TableGen/DAGISelMatcher.cpp Fri Nov 30 06:15:13 2018
@@ -93,13 +93,23 @@ SwitchTypeMatcher::~SwitchTypeMatcher()
delete C.second;
}
-CheckPredicateMatcher::CheckPredicateMatcher(const TreePredicateFn &pred)
- : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()) {}
+CheckPredicateMatcher::CheckPredicateMatcher(
+ const TreePredicateFn &pred, const SmallVectorImpl<unsigned> &Ops)
+ : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()),
+ Operands(Ops.begin(), Ops.end()) {}
TreePredicateFn CheckPredicateMatcher::getPredicate() const {
return TreePredicateFn(Pred);
}
+unsigned CheckPredicateMatcher::getNumOperands() const {
+ return Operands.size();
+}
+
+unsigned CheckPredicateMatcher::getOperandNo(unsigned i) const {
+ assert(i < Operands.size());
+ return Operands[i];
+}
// printImpl methods.
Modified: llvm/trunk/utils/TableGen/DAGISelMatcher.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DAGISelMatcher.h?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/DAGISelMatcher.h (original)
+++ llvm/trunk/utils/TableGen/DAGISelMatcher.h Fri Nov 30 06:15:13 2018
@@ -414,10 +414,14 @@ private:
/// see if the node is acceptable.
class CheckPredicateMatcher : public Matcher {
TreePattern *Pred;
+ const SmallVector<unsigned, 4> Operands;
public:
- CheckPredicateMatcher(const TreePredicateFn &pred);
+ CheckPredicateMatcher(const TreePredicateFn &pred,
+ const SmallVectorImpl<unsigned> &Operands);
TreePredicateFn getPredicate() const;
+ unsigned getNumOperands() const;
+ unsigned getOperandNo(unsigned i) const;
static bool classof(const Matcher *N) {
return N->getKind() == CheckPredicate;
Modified: llvm/trunk/utils/TableGen/DAGISelMatcherEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DAGISelMatcherEmitter.cpp?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/DAGISelMatcherEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/DAGISelMatcherEmitter.cpp Fri Nov 30 06:15:13 2018
@@ -50,6 +50,7 @@ class MatcherTableEmitter {
DenseMap<TreePattern *, unsigned> NodePredicateMap;
std::vector<TreePredicateFn> NodePredicates;
+ std::vector<TreePredicateFn> NodePredicatesWithOperands;
// We de-duplicate the predicates by code string, and use this map to track
// all the patterns with "identical" predicates.
@@ -92,6 +93,9 @@ public:
void EmitPatternMatchTable(raw_ostream &OS);
private:
+ void EmitNodePredicatesFunction(const std::vector<TreePredicateFn> &Preds,
+ StringRef Decl, raw_ostream &OS);
+
unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
raw_ostream &OS);
@@ -103,12 +107,20 @@ private:
NodePredicatesByCodeToRun[Pred.getCodeToRunOnSDNode()];
if (SameCodePreds.empty()) {
// We've never seen a predicate with the same code: allocate an entry.
- NodePredicates.push_back(Pred);
- Entry = NodePredicates.size();
+ if (Pred.usesOperands()) {
+ NodePredicatesWithOperands.push_back(Pred);
+ Entry = NodePredicatesWithOperands.size();
+ } else {
+ NodePredicates.push_back(Pred);
+ Entry = NodePredicates.size();
+ }
} else {
// We did see an identical predicate: re-use it.
Entry = NodePredicateMap[SameCodePreds.front()];
assert(Entry != 0);
+ assert(TreePredicateFn(SameCodePreds.front()).usesOperands() ==
+ Pred.usesOperands() &&
+ "PatFrags with some code must have same usesOperands setting");
}
// In both cases, we've never seen this particular predicate before, so
// mark it in the list of predicates sharing the same code.
@@ -396,11 +408,23 @@ EmitMatcher(const Matcher *N, unsigned I
}
case Matcher::CheckPredicate: {
TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate();
- OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ',';
+ unsigned OperandBytes = 0;
+
+ if (Pred.usesOperands()) {
+ unsigned NumOps = cast<CheckPredicateMatcher>(N)->getNumOperands();
+ OS << "OPC_CheckPredicateWithOperands, " << NumOps << "/*#Ops*/, ";
+ for (unsigned i = 0; i < NumOps; ++i)
+ OS << cast<CheckPredicateMatcher>(N)->getOperandNo(i) << ", ";
+ OperandBytes = 1 + NumOps;
+ } else {
+ OS << "OPC_CheckPredicate, ";
+ }
+
+ OS << getNodePredicate(Pred) << ',';
if (!OmitComments)
OS << " // " << Pred.getFnName();
OS << '\n';
- return 2;
+ return 2 + OperandBytes;
}
case Matcher::CheckOpcode:
@@ -783,6 +807,33 @@ EmitMatcherList(const Matcher *N, unsign
return Size;
}
+void MatcherTableEmitter::EmitNodePredicatesFunction(
+ const std::vector<TreePredicateFn> &Preds, StringRef Decl,
+ raw_ostream &OS) {
+ if (Preds.empty())
+ return;
+
+ BeginEmitFunction(OS, "bool", Decl, true/*AddOverride*/);
+ OS << "{\n";
+ OS << " switch (PredNo) {\n";
+ OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n";
+ for (unsigned i = 0, e = Preds.size(); i != e; ++i) {
+ // Emit the predicate code corresponding to this pattern.
+ TreePredicateFn PredFn = Preds[i];
+
+ assert(!PredFn.isAlwaysTrue() && "No code in this predicate");
+ OS << " case " << i << ": { \n";
+ for (auto *SimilarPred :
+ NodePredicatesByCodeToRun[PredFn.getCodeToRunOnSDNode()])
+ OS << " // " << TreePredicateFn(SimilarPred).getFnName() <<'\n';
+
+ OS << PredFn.getCodeToRunOnSDNode() << "\n }\n";
+ }
+ OS << " }\n";
+ OS << "}\n";
+ EndEmitFunction(OS);
+}
+
void MatcherTableEmitter::EmitPredicateFunctions(raw_ostream &OS) {
// Emit pattern predicates.
if (!PatternPredicates.empty()) {
@@ -799,29 +850,14 @@ void MatcherTableEmitter::EmitPredicateF
}
// Emit Node predicates.
- if (!NodePredicates.empty()) {
- BeginEmitFunction(OS, "bool",
- "CheckNodePredicate(SDNode *Node, unsigned PredNo) const",
- true/*AddOverride*/);
- OS << "{\n";
- OS << " switch (PredNo) {\n";
- OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n";
- for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) {
- // Emit the predicate code corresponding to this pattern.
- TreePredicateFn PredFn = NodePredicates[i];
-
- assert(!PredFn.isAlwaysTrue() && "No code in this predicate");
- OS << " case " << i << ": { \n";
- for (auto *SimilarPred :
- NodePredicatesByCodeToRun[PredFn.getCodeToRunOnSDNode()])
- OS << " // " << TreePredicateFn(SimilarPred).getFnName() <<'\n';
-
- OS << PredFn.getCodeToRunOnSDNode() << "\n }\n";
- }
- OS << " }\n";
- OS << "}\n";
- EndEmitFunction(OS);
- }
+ EmitNodePredicatesFunction(
+ NodePredicates, "CheckNodePredicate(SDNode *Node, unsigned PredNo) const",
+ OS);
+ EmitNodePredicatesFunction(
+ NodePredicatesWithOperands,
+ "CheckNodePredicateWithOperands(SDNode *Node, unsigned PredNo, "
+ "const SmallVectorImpl<SDValue> &Operands) const",
+ OS);
// Emit CompletePattern matchers.
// FIXME: This should be const.
Modified: llvm/trunk/utils/TableGen/DAGISelMatcherGen.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DAGISelMatcherGen.cpp?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/DAGISelMatcherGen.cpp (original)
+++ llvm/trunk/utils/TableGen/DAGISelMatcherGen.cpp Fri Nov 30 06:15:13 2018
@@ -120,7 +120,7 @@ namespace {
/// If this is the first time a node with unique identifier Name has been
/// seen, record it. Otherwise, emit a check to make sure this is the same
/// node. Returns true if this is the first encounter.
- bool recordUniqueNode(const std::string &Name);
+ bool recordUniqueNode(ArrayRef<std::string> Names);
// Result Code Generation.
unsigned getNamedArgumentSlot(StringRef Name) {
@@ -319,8 +319,8 @@ void MatcherGen::EmitOperatorMatchCode(c
// to handle this.
if ((N->getOperator()->getName() == "and" ||
N->getOperator()->getName() == "or") &&
- N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty() &&
- N->getPredicateFns().empty()) {
+ N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateCalls().empty() &&
+ N->getPredicateCalls().empty()) {
if (IntInit *II = dyn_cast<IntInit>(N->getChild(1)->getLeafValue())) {
if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
// If this is at the root of the pattern, we emit a redundant
@@ -441,21 +441,39 @@ void MatcherGen::EmitOperatorMatchCode(c
}
}
-bool MatcherGen::recordUniqueNode(const std::string &Name) {
- unsigned &VarMapEntry = VariableMap[Name];
- if (VarMapEntry == 0) {
+bool MatcherGen::recordUniqueNode(ArrayRef<std::string> Names) {
+ unsigned Entry = 0;
+ for (const std::string &Name : Names) {
+ unsigned &VarMapEntry = VariableMap[Name];
+ if (!Entry)
+ Entry = VarMapEntry;
+ assert(Entry == VarMapEntry);
+ }
+
+ bool NewRecord = false;
+ if (Entry == 0) {
// If it is a named node, we must emit a 'Record' opcode.
- AddMatcher(new RecordMatcher("$" + Name, NextRecordedOperandNo));
- VarMapEntry = ++NextRecordedOperandNo;
- return true;
+ std::string WhatFor;
+ for (const std::string &Name : Names) {
+ if (!WhatFor.empty())
+ WhatFor += ',';
+ WhatFor += "$" + Name;
+ }
+ AddMatcher(new RecordMatcher(WhatFor, NextRecordedOperandNo));
+ Entry = ++NextRecordedOperandNo;
+ NewRecord = true;
+ } else {
+ // If we get here, this is a second reference to a specific name. Since
+ // we already have checked that the first reference is valid, we don't
+ // have to recursively match it, just check that it's the same as the
+ // previously named thing.
+ AddMatcher(new CheckSameMatcher(Entry-1));
}
- // If we get here, this is a second reference to a specific name. Since
- // we already have checked that the first reference is valid, we don't
- // have to recursively match it, just check that it's the same as the
- // previously named thing.
- AddMatcher(new CheckSameMatcher(VarMapEntry-1));
- return false;
+ for (const std::string &Name : Names)
+ VariableMap[Name] = Entry;
+
+ return NewRecord;
}
void MatcherGen::EmitMatchCode(const TreePatternNode *N,
@@ -475,9 +493,18 @@ void MatcherGen::EmitMatchCode(const Tre
// If this node has a name associated with it, capture it in VariableMap. If
// we already saw this in the pattern, emit code to verify dagness.
+ SmallVector<std::string, 4> Names;
if (!N->getName().empty())
- if (!recordUniqueNode(N->getName()))
+ Names.push_back(N->getName());
+
+ for (const ScopedName &Name : N->getNamesAsPredicateArg()) {
+ Names.push_back(("pred:" + Twine(Name.getScope()) + ":" + Name.getIdentifier()).str());
+ }
+
+ if (!Names.empty()) {
+ if (!recordUniqueNode(Names))
return;
+ }
if (N->isLeaf())
EmitLeafMatchCode(N);
@@ -485,8 +512,19 @@ void MatcherGen::EmitMatchCode(const Tre
EmitOperatorMatchCode(N, NodeNoTypes, ForceMode);
// If there are node predicates for this node, generate their checks.
- for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
- AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i]));
+ for (unsigned i = 0, e = N->getPredicateCalls().size(); i != e; ++i) {
+ const TreePredicateCall &Pred = N->getPredicateCalls()[i];
+ SmallVector<unsigned, 4> Operands;
+ if (Pred.Fn.usesOperands()) {
+ TreePattern *TP = Pred.Fn.getOrigPatFragRecord();
+ for (unsigned i = 0; i < TP->getNumArgs(); ++i) {
+ std::string Name =
+ ("pred:" + Twine(Pred.Scope) + ":" + TP->getArgName(i)).str();
+ Operands.push_back(getNamedArgumentSlot(Name));
+ }
+ }
+ AddMatcher(new CheckPredicateMatcher(Pred.Fn, Operands));
+ }
for (unsigned i = 0, e = ResultsToTypeCheck.size(); i != e; ++i)
AddMatcher(new CheckTypeMatcher(N->getSimpleType(ResultsToTypeCheck[i]),
Modified: llvm/trunk/utils/TableGen/FastISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/FastISelEmitter.cpp?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/FastISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/FastISelEmitter.cpp Fri Nov 30 06:15:13 2018
@@ -210,13 +210,13 @@ struct OperandsSignature {
// Handle imm operands specially.
if (!Op->isLeaf() && Op->getOperator()->getName() == "imm") {
unsigned PredNo = 0;
- if (!Op->getPredicateFns().empty()) {
- TreePredicateFn PredFn = Op->getPredicateFns()[0];
+ if (!Op->getPredicateCalls().empty()) {
+ TreePredicateFn PredFn = Op->getPredicateCalls()[0].Fn;
// If there is more than one predicate weighing in on this operand
// then we don't handle it. This doesn't typically happen for
// immediates anyway.
- if (Op->getPredicateFns().size() > 1 ||
- !PredFn.isImmediatePattern())
+ if (Op->getPredicateCalls().size() > 1 ||
+ !PredFn.isImmediatePattern() || PredFn.usesOperands())
return false;
// Ignore any instruction with 'FastIselShouldIgnore', these are
// not needed and just bloat the fast instruction selector. For
@@ -236,7 +236,7 @@ struct OperandsSignature {
// For now, filter out any operand with a predicate.
// For now, filter out any operand with multiple values.
- if (!Op->getPredicateFns().empty() || Op->getNumTypes() != 1)
+ if (!Op->getPredicateCalls().empty() || Op->getNumTypes() != 1)
return false;
if (!Op->isLeaf()) {
@@ -529,7 +529,7 @@ void FastISelMap::collectPatterns(CodeGe
}
// For now, filter out any instructions with predicates.
- if (!InstPatNode->getPredicateFns().empty())
+ if (!InstPatNode->getPredicateCalls().empty())
continue;
// Check all the operands.
Modified: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp?rev=347992&r1=347991&r2=347992&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp Fri Nov 30 06:15:13 2018
@@ -200,7 +200,8 @@ static Optional<LLTCodeGen> MVTToLLT(MVT
static std::string explainPredicates(const TreePatternNode *N) {
std::string Explanation = "";
StringRef Separator = "";
- for (const auto &P : N->getPredicateFns()) {
+ for (const TreePredicateCall &Call : N->getPredicateCalls()) {
+ const TreePredicateFn &P = Call.Fn;
Explanation +=
(Separator + P.getOrigPatFragRecord()->getRecord()->getName()).str();
Separator = ", ";
@@ -284,7 +285,9 @@ static Error isTrivialOperatorNode(const
std::string Separator = "";
bool HasUnsupportedPredicate = false;
- for (const auto &Predicate : N->getPredicateFns()) {
+ for (const TreePredicateCall &Call : N->getPredicateCalls()) {
+ const TreePredicateFn &Predicate = Call.Fn;
+
if (Predicate.isAlwaysTrue())
continue;
@@ -3117,7 +3120,8 @@ Record *GlobalISelEmitter::findNodeEquiv
const CodeGenInstruction *
GlobalISelEmitter::getEquivNode(Record &Equiv, const TreePatternNode *N) const {
- for (const auto &Predicate : N->getPredicateFns()) {
+ for (const TreePredicateCall &Call : N->getPredicateCalls()) {
+ const TreePredicateFn &Predicate = Call.Fn;
if (!Equiv.isValueUnset("IfSignExtend") && Predicate.isLoad() &&
Predicate.isSignExtLoad())
return &Target.getInstruction(Equiv.getValueAsDef("IfSignExtend"));
@@ -3186,7 +3190,8 @@ Expected<InstructionMatcher &> GlobalISe
" for result of Src pattern operator");
}
- for (const auto &Predicate : Src->getPredicateFns()) {
+ for (const TreePredicateCall &Call : Src->getPredicateCalls()) {
+ const TreePredicateFn &Predicate = Call.Fn;
if (Predicate.isAlwaysTrue())
continue;
More information about the llvm-commits
mailing list